|
| 1 | +/* |
| 2 | + server/weapons/ray_gun.qc |
| 3 | +
|
| 4 | + Core logic for the Ballistic Knife special weapon. |
| 5 | +
|
| 6 | + Copyright (C) 2021-2025 NZ:P Team |
| 7 | +
|
| 8 | + This program is free software; you can redistribute it and/or |
| 9 | + modify it under the terms of the GNU General Public License |
| 10 | + as published by the Free Software Foundation; either version 2 |
| 11 | + of the License, or (at your option) any later version. |
| 12 | +
|
| 13 | + This program is distributed in the hope that it will be useful, |
| 14 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| 16 | +
|
| 17 | + See the GNU General Public License for more details. |
| 18 | +
|
| 19 | + You should have received a copy of the GNU General Public License |
| 20 | + along with this program; if not, write to: |
| 21 | +
|
| 22 | + Free Software Foundation, Inc. |
| 23 | + 59 Temple Place - Suite 330 |
| 24 | + Boston, MA 02111-1307, USA |
| 25 | +
|
| 26 | +*/ |
| 27 | + |
| 28 | +void() Parse_Damage; |
| 29 | + |
| 30 | +void(entity victim) Blade_Damage = |
| 31 | +{ |
| 32 | + float damage_type = 0; |
| 33 | + float damage_region = 0; |
| 34 | + |
| 35 | + switch(victim.classname) { |
| 36 | + case "ai_zombie_head": |
| 37 | + damage_region = HEAD_X; |
| 38 | + damage_type = DMG_TYPE_HEADSHOT; |
| 39 | + break; |
| 40 | + case "ai_zombie_larm": |
| 41 | + case "ai_zombie_rarm": |
| 42 | + damage_region = LIMBS_X; |
| 43 | + damage_type = DMG_TYPE_OTHER; |
| 44 | + break; |
| 45 | + case "ai_zombie": |
| 46 | + if (trace_endpos_z < victim.origin_z) { |
| 47 | + damage_region = LOWER_TORSO_X; |
| 48 | + damage_type = DMG_TYPE_LOWERTORSO; |
| 49 | + } |
| 50 | + else { |
| 51 | + damage_region = UPPER_TORSO_X; |
| 52 | + damage_type = DMG_TYPE_UPPERTORSO; |
| 53 | + } |
| 54 | + break; |
| 55 | + default: |
| 56 | + damage_region = LOWER_TORSO_X; |
| 57 | + damage_type = DMG_TYPE_LOWERTORSO; |
| 58 | + break; |
| 59 | + } |
| 60 | + |
| 61 | + DamageHandler(victim, self.owner, getWeaponDamage(self.weapon) * getWeaponMultiplier(self.weapon, damage_region), damage_type); |
| 62 | + self.angles_y = 180; |
| 63 | +}; |
| 64 | + |
| 65 | +void(entity client) Blade_Revive = |
| 66 | +{ |
| 67 | + // Reward the revivee with the points the downed client lost, |
| 68 | + // and increment their revives stat. |
| 69 | + Player_AddScore(self.owner, other.requirespower, false); |
| 70 | + self.owner.revives++; |
| 71 | + |
| 72 | + entity old_self = self; |
| 73 | + self = other; |
| 74 | + GetUp(); |
| 75 | + self = old_self; |
| 76 | + |
| 77 | + // Remove the revive icon from above the previously downed client |
| 78 | + DisableReviveIcon(other.playernum); |
| 79 | +}; |
| 80 | + |
| 81 | +// |
| 82 | +// Blade_VelocityIncrease() |
| 83 | +// Constant think function to speed up the Beam gradually. |
| 84 | +// |
| 85 | +void() Blade_VelocityIncrease = |
| 86 | +{ |
| 87 | + self.angles = vectoangles(self.velocity); |
| 88 | + self.angles_z += (self.angles_z + 180 < 360)? 180 : -180; |
| 89 | + |
| 90 | + self.velocity *= 1.5; |
| 91 | + self.nextthink = time + 0.1; |
| 92 | +} |
| 93 | + |
| 94 | +void() Blade_Die = |
| 95 | +{ |
| 96 | + remove(self); |
| 97 | +}; |
| 98 | + |
| 99 | +void() Blade_Pickup = |
| 100 | +{ |
| 101 | + if (other != self.owner) |
| 102 | + return; |
| 103 | + |
| 104 | + if (EqualNonPapWeapon(self.owner.weapon) != EqualNonPapWeapon(self.weapon)) |
| 105 | + return; |
| 106 | + |
| 107 | + if (self.owner.weapons[0].weapon_reserve >= getWeaponAmmo(self.owner.weapon)) |
| 108 | + return; |
| 109 | + |
| 110 | + self.owner.weapons[0].weapon_reserve++; |
| 111 | + Blade_Die(); |
| 112 | +}; |
| 113 | + |
| 114 | +// |
| 115 | +// Blade_Impact() |
| 116 | +// When something touches the Blade, check it's state |
| 117 | +// to decide whether to inflict damage or revive a player. |
| 118 | +// |
| 119 | +void() Blade_Impact = |
| 120 | +{ |
| 121 | + if (!other.solid || other.solid == SOLID_TRIGGER) |
| 122 | + if (other != world) |
| 123 | + return; |
| 124 | + |
| 125 | + if (other == self.owner) |
| 126 | + return; |
| 127 | + |
| 128 | + // Damage monster.. |
| 129 | + if (other.flags & FL_MONSTER) { |
| 130 | + Blade_Damage(other); |
| 131 | + } |
| 132 | + // Revive teammate.. |
| 133 | + else if ((other.flags & FL_CLIENT) && self.has_bowie_knife == true) { |
| 134 | + if (other.downed) |
| 135 | + Blade_Revive(other); |
| 136 | + } |
| 137 | + |
| 138 | + // Lose all velocity, drop to floor.. |
| 139 | + self.velocity = '0 0 0'; |
| 140 | + self.movetype = MOVETYPE_NONE; |
| 141 | + Spawns_DropToFloor(self); |
| 142 | + |
| 143 | + self.skin = 1; |
| 144 | + self.solid = SOLID_TRIGGER; |
| 145 | + self.touch = Blade_Pickup; |
| 146 | + self.effects = EF_FULLBRIGHT; |
| 147 | + self.think = Blade_Die; |
| 148 | + self.nextthink = time + 60; |
| 149 | +}; |
| 150 | + |
| 151 | +// |
| 152 | +// W_FireBlade() |
| 153 | +// Called by weapon_core for the Blade firetype. Sets up the |
| 154 | +// blade and prepares it for impact and force forward. |
| 155 | +// |
| 156 | +void() W_FireBlade = |
| 157 | +{ |
| 158 | + // Initially define the blade. |
| 159 | + entity blade; |
| 160 | + blade = spawn(); |
| 161 | + blade.owner = self; |
| 162 | + blade.movetype = MOVETYPE_BOUNCE; |
| 163 | + blade.weapon = self.weapon; |
| 164 | + blade.solid = SOLID_BBOX; |
| 165 | + blade.classname = "projectile_blade"; |
| 166 | + |
| 167 | + // Start initial velocity projection. |
| 168 | + makevectors(self.v_angle); |
| 169 | + blade.velocity = v_forward*1750 + v_up*20; |
| 170 | + blade.avelocity = '0 0 0'; |
| 171 | + |
| 172 | + // Make sure our angle is always FORWARD |
| 173 | + blade.angles = vectoangles(blade.velocity); |
| 174 | + blade.angles_z += (blade.angles_z + 180 < 360)? 180 : -180; |
| 175 | + blade.angles = vectoangles(v_forward); |
| 176 | + blade.v_angle = '0 0 200'; |
| 177 | + |
| 178 | + blade.weapon = blade.owner.weapon; |
| 179 | + |
| 180 | + // Upgraded Blades can revive teammates |
| 181 | + if (blade.owner.weapon == EqualPapWeapon(blade.owner.weapon)) { |
| 182 | + blade.has_bowie_knife = true; // reuse of an entvar |
| 183 | + } |
| 184 | + |
| 185 | + // Prepare for Impact and Force forward. |
| 186 | + blade.touch = Blade_Impact; |
| 187 | + blade.think = Blade_VelocityIncrease; |
| 188 | + blade.nextthink = time + 0.1; |
| 189 | + |
| 190 | + // Set model. |
| 191 | + setmodel(blade, "models/weapons/bk/blade.mdl"); |
| 192 | + |
| 193 | + // final setup! |
| 194 | + blade.origin = self.origin + self.view_ofs; |
| 195 | + blade.origin += v_forward * 0; |
| 196 | + |
| 197 | + makevectors(self.v_angle); |
| 198 | + blade.origin += v_up * -1; |
| 199 | + |
| 200 | + setorigin(blade, blade.origin); |
| 201 | + |
| 202 | + self.animend = ReturnWeaponModel; |
| 203 | + self.callfuncat = 0; |
| 204 | +} |
0 commit comments