void weapon_arm_fire (edict_t *ent) { vec3_t start; vec3_t forward, right; vec3_t offset; int damage; iteminfo_t *info = getWornItemInfo(ent, 0); int kick = info->arg9; int refire = info->arg3 + 2; int recycle = info->arg4 + 1; int range = info->arg5; int count = info->arg6;// + (int) (info->arg6 * ent->client->pers.skill[3]); int cost = info->arg10; if (refire < 2) refire = 2; if (recycle < 1) recycle = 1; cost *= ((float) (ent->client->max_magic + 1200.0)) / 1200.0; damage = (int) ceil(info->arg1 + info->arg2 * (float) ent->client->pers.skill[1]); if ((!(ent->client->buttons & BUTTON_ATTACK)) || (ent->client->magic < cost)) { ent->client->ps.gunframe = 9 + recycle; return; } ent->client->magic -= cost; if (ent->client->magregentime < level.time + 0.5) ent->client->magregentime = level.time + 0.5; /* if (ent->client->ps.gunframe == 9) { ent->client->ps.gunframe++; return; }*/ AngleVectors (ent->client->v_angle, forward, right, NULL); VectorScale (forward, -2, ent->client->kick_origin); ent->client->kick_angles[0] = -2; VectorSet(offset, 0, 8, ent->viewheight-8); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); damage = applyWeaponBonuses(ent, damage, count); if (is_quad) kick *= 4; fire_armblast(ent, start, forward, damage, kick, info->arg7, info->arg8, count, range, MOD_ARM); ent->client->silencer_shots-=4; // send muzzle flash if ((ent->client->silencer_shots > 0) && (ent->client->pers.skill[58] > 7)) { ent->client->silencer_shots -= 1; } else { gi.sound(ent, CHAN_AUTO, gi.soundindex("parasite/paratck2.wav"), 1, ATTN_NORM, 0); gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent-g_edicts); gi.WriteByte (MZ_NUKE1); gi.multicast (ent->s.origin, MULTICAST_PVS); /* gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent-g_edicts); gi.WriteByte (MZ_SHOTGUN | is_silenced); gi.multicast (ent->s.origin, MULTICAST_PVS);*/ } if ((ent->client->ps.gunframe == 9) && (ent->client->buttons & BUTTON_ATTACK)) { ent->client->ps.gunframe -= refire; } ent->client->ps.gunframe++; // if (!(ent->client->buttons & BUTTON_ATTACK)) // ent->client->ps.gunframe += recycle; PlayerNoise(ent, start, PNOISE_WEAPON); // if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ent->client->pers.inventory[ent->client->ammo_index]--; }
void P_FollowWall (edict_t *ent) { int turns=0, num=90; vec3_t forward, right, start, end; vec3_t offset, angles; trace_t tr; AngleVectors (ent->client->v_angle, forward, right, NULL); VectorSet(offset, 0, 7, ent->viewheight-8); P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start); VectorMA(start, 8192, forward, end); tr = gi.trace(start, NULL, NULL, end, ent, MASK_SOLID); VectorCopy(tr.endpos, end); vectoangles(tr.plane.normal, angles); ValidateAngles(angles); VectorCopy(tr.endpos, start); gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_BFG_LASER); gi.WritePosition (ent->s.origin); gi.WritePosition (tr.endpos); gi.multicast (ent->s.origin, MULTICAST_PHS); while (turns < 10) { angles[YAW] += num; forward[0] = cos(DEG2RAD(angles[YAW])); forward[1] = sin(DEG2RAD(angles[YAW])); forward[2] = 0; VectorMA(start, 8192, forward, end); tr = gi.trace(start, NULL, NULL, end, ent, MASK_SOLID); if (tr.startsolid || tr.allsolid) { num = -90; gi.dprintf("fail\n"); continue; } gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_BFG_LASER); gi.WritePosition (start); gi.WritePosition (tr.endpos); gi.multicast (start, MULTICAST_PHS); VectorCopy(tr.endpos, start); vectoangles(tr.plane.normal, angles); ValidateAngles(angles); turns++; //gi.dprintf("turn %d %d degrees\n", turns, (int)angles[YAW]); } /* while (1) { angles[YAW] += num; forward[0] = cos(DEG2RAD(angles[YAW])); forward[1] = sin(DEG2RAD(angles[YAW])); forward[2] = 0; VectorMA(start, 48, forward, end); tr = gi.trace(start, NULL, NULL, end, ent, MASK_SOLID); if (tr.fraction < 1) { if (num == -180) break; num = -180; continue; } gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_BFG_LASER); gi.WritePosition (start); gi.WritePosition (tr.endpos); gi.multicast (start, MULTICAST_PHS); break; } */ }
void Chaingun_Fire (edict_t *ent) { int shots, flash_shots = 1; vec3_t start; vec3_t forward, right, up; float r, u; vec3_t offset; int damage; int kick = 0; int item = getWornItem(ent, GIEX_ITEM_WEAPON); iteminfo_t *info = getWornItemInfo(ent, 0); int i, spread = getMachinegunSpread(ent, item, info); // damage = info->arg1 + info->arg2 * ent->client->pers.skill[1]; damage = getChaingunDamage(ent, item, info); if (ent->client->ps.gunframe == 5) { if ((ent->client->silencer_shots > 0) && (ent->client->pers.skill[58] > 6)) { ent->client->silencer_shots -= 1; } else { gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnu1a.wav"), 1, ATTN_IDLE, 0); } ent->client->ps.gunframe += ent->client->pers.skill[5]; } if ((ent->client->ps.gunframe == 14) && !(ent->client->buttons & BUTTON_ATTACK)) { ent->client->ps.gunframe = 32; // End firing ent->client->weapon_sound = 0; return; } else if ((ent->client->ps.gunframe == 21) && (ent->client->buttons & BUTTON_ATTACK) && ent->client->pers.inventory[ent->client->ammo_index]) { ent->client->ps.gunframe = 15; // Loop back } else { ent->client->ps.gunframe++; } if (ent->client->ps.gunframe == 22) { ent->client->weapon_sound = 0; if ((ent->client->silencer_shots > 0) && (ent->client->pers.skill[58] > 6)) { ent->client->silencer_shots -= 1; } else { gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnd1a.wav"), 1, ATTN_IDLE, 0); } ent->client->ps.gunframe += ent->client->pers.skill[5]; } else { if ((ent->client->silencer_shots > 0) && (ent->client->pers.skill[58] > 6)) { ent->client->silencer_shots -= 1; } else { ent->client->weapon_sound = gi.soundindex("weapons/chngnl1a.wav"); } } ent->client->anim_priority = ANIM_ATTACK; if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) { ent->s.frame = FRAME_crattak1 - (ent->client->ps.gunframe & 1); ent->client->anim_end = FRAME_crattak9; } else { ent->s.frame = FRAME_attack1 - (ent->client->ps.gunframe & 1); ent->client->anim_end = FRAME_attack8; } if (ent->client->ps.gunframe <= 9) { shots = info->arg4; } else if (ent->client->ps.gunframe <= 14) { if (ent->client->buttons & BUTTON_ATTACK) { shots = info->arg4 + 1; flash_shots = 2; } else { shots = info->arg4; flash_shots = 1; } } else { // 15 - 20 if ((ent->client->ps.gunframe == 18) || (ent->client->ps.gunframe == 20)) { shots = info->arg4 + 2; flash_shots = 2; } else { shots = info->arg4 + 1; flash_shots = 1; } } if (shots < 1) shots = 1; if (ent->client->pers.inventory[ent->client->ammo_index] < shots) { shots = ent->client->pers.inventory[ent->client->ammo_index]; } if (!shots) { if (level.time >= ent->pain_debounce_time) { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ent->pain_debounce_time = level.time + 1; } NoAmmoWeaponChange (ent); return; } damage = applyWeaponBonuses(ent, damage, 1); // if (is_quad) // kick *= 4; for (i=0 ; i<3 ; i++) { ent->client->kick_origin[i] = crandom() * 0.35; ent->client->kick_angles[i] = crandom() * 0.7; } for (i=0 ; i<shots ; i++) { // get start / end positions AngleVectors (ent->client->v_angle, forward, right, up); r = 7 + crandom()*4; u = crandom()*4; VectorSet(offset, 0, r, u + ent->viewheight-8); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); fire_bullet (ent, start, forward, damage, kick, spread, spread, MOD_CHAINGUN); } // send muzzle flash if ((ent->client->silencer_shots > 0) && (ent->client->pers.skill[58] > 7)) { ent->client->silencer_shots -= shots; } else { gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent-g_edicts); gi.WriteByte ((MZ_CHAINGUN1 + flash_shots) | is_silenced); gi.multicast (ent->s.origin, MULTICAST_PVS); } ent->client->silencer_shots-=3; PlayerNoise(ent, start, PNOISE_WEAPON); // if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ent->client->pers.inventory[ent->client->ammo_index] -= shots; }
void weapon_supershotgun_fire (edict_t *ent) { vec3_t start; vec3_t forward, right; vec3_t offset; vec3_t v; iteminfo_t *info = getWornItemInfo(ent, 0); int damage; int ammo; int kick = 9; int count = (info->arg4 + (int)(info->arg5 * ent->client->pers.skill[3])) / 2; damage = (int) ceil(info->arg1 + info->arg2 * (float) ent->client->pers.skill[1]) * 0.5; //(info->arg4 / 2)); damage /= count; // damage = info->arg1 + (int) ceil(info->arg2 * ent->client->pers.skill[1]); AngleVectors (ent->client->v_angle, forward, right, NULL); VectorScale (forward, -2, ent->client->kick_origin); ent->client->kick_angles[0] = -2; VectorSet(offset, 0, 8, ent->viewheight-8); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); damage = applyWeaponBonuses(ent, damage, count); if (is_quad) kick *= 4; v[PITCH] = ent->client->v_angle[PITCH]; v[ROLL] = ent->client->v_angle[ROLL]; if (ent->client->ps.gunframe == 7) { v[YAW] = ent->client->v_angle[YAW] - 5; AngleVectors (v, forward, NULL, NULL); fire_shotgun (ent, start, forward, damage, kick, info->arg6, info->arg6, count, MOD_SSHOTGUN); if (info->arg7 == 0) { v[YAW] = ent->client->v_angle[YAW] + 5; AngleVectors (v, forward, NULL, NULL); fire_shotgun (ent, start, forward, damage, kick, info->arg6, info->arg6, count, MOD_SSHOTGUN); } } else { v[YAW] = ent->client->v_angle[YAW] + 5; AngleVectors (v, forward, NULL, NULL); fire_shotgun (ent, start, forward, damage, kick, info->arg6, info->arg6, count, MOD_SSHOTGUN); } ent->client->silencer_shots-=3; // send muzzle flash if ((ent->client->silencer_shots > 0) && (ent->client->pers.skill[58] > 7)) { ent->client->silencer_shots -= 1; } else { gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent-g_edicts); gi.WriteByte (MZ_SSHOTGUN | is_silenced); gi.multicast (ent->s.origin, MULTICAST_PVS); } ent->client->ps.gunframe++; PlayerNoise(ent, start, PNOISE_WEAPON); // if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) { ammo = 1; if (info->arg7 == 0) { ammo = 2; } ent->client->pers.inventory[ent->client->ammo_index] -= ammo; // } }
void weapon_railgun_fire (edict_t *ent) { vec3_t start; vec3_t forward, right; vec3_t offset; int damage; int kick; //RAV if(ent->client->pers.pl_state ==5 ) return; if( ent->client->pers.pl_state < 1 || ent->client->resp.spectator ||(ctf->value && ent->client->resp.ctf_team < 1)) { ent->movetype = MOVETYPE_NOCLIP; ent->solid = SOLID_NOT; ent->svflags |= SVF_NOCLIENT; ent->client->resp.ctf_team = CTF_NOTEAM; ent->client->ps.gunindex = 0; ent->client->pers.pl_state = 0; gi.linkentity (ent); ent->client->resp.spectator = true; return; } // if (deathmatch->value) { // normal damage is too extreme in dm damage = rg_damage->value; kick = rg_kick->value; } else { damage = 150; kick = 250; } if (is_quad) { damage *= 4; kick *= 4; }//DB if (is_strength) { damage *= 2; kick *= 2; } //DB //RAV if(voosh->value) { damage = (int)raildamage->value; kick = (int)railkick->value; } // AngleVectors (ent->client->v_angle, forward, right, NULL); VectorScale (forward, -3, ent->client->kick_origin); ent->client->kick_angles[0] = -3; VectorSet(offset, 0, 7, ent->viewheight-8); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); fire_rail (ent, start, forward, damage, kick); // send muzzle flash gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent-g_edicts); gi.WriteByte (MZ_RAILGUN | is_silenced); gi.multicast (ent->s.origin, MULTICAST_PVS); ent->client->ps.gunframe++; PlayerNoise(ent, start, PNOISE_WEAPON); //RAV //allow for camper checking ent->client->check_camping = true; // if (! ( dmflag & DF_INFINITE_AMMO ) ) if(voosh->value == 0)//RAV ent->client->pers.inventory[ent->client->ammo_index]--; }
void Machinegun_Fire (edict_t *ent) { vec3_t start; vec3_t forward, right; vec3_t angles; int damage; int kick = 0; vec3_t offset; int item = getWornItem(ent, GIEX_ITEM_WEAPON); iteminfo_t *info = getWornItemInfo(ent, GIEX_ITEM_WEAPON); int i, spread = getMachinegunSpread(ent, item, info); // damage = info->arg1 + info->arg2 * ent->client->pers.skill[1]; damage = getMachinegunDamage(ent, item, info); if (!(ent->client->buttons & BUTTON_ATTACK)) { ent->client->ps.gunframe++; return; } if (ent->client->ps.gunframe == 5) ent->client->ps.gunframe = 4; else ent->client->ps.gunframe = 5; if (ent->client->pers.inventory[ent->client->ammo_index] < 1) { ent->client->ps.gunframe = 6; if (level.time >= ent->pain_debounce_time) { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ent->pain_debounce_time = level.time + 1; } NoAmmoWeaponChange (ent); return; } damage = applyWeaponBonuses(ent, damage, 1); // if (is_quad) // kick *= 4; for (i=1 ; i<3 ; i++) { ent->client->kick_origin[i] = crandom() * 0.35; ent->client->kick_angles[i] = crandom() * 0.7; } ent->client->kick_origin[0] = crandom() * 0.35; // get start / end positions VectorAdd (ent->client->v_angle, ent->client->kick_angles, angles); AngleVectors (angles, forward, right, NULL); VectorSet(offset, 0, 8, ent->viewheight-8); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); fire_bullet (ent, start, forward, damage, kick, spread, spread, MOD_MACHINEGUN); if ((ent->client->silencer_shots > 0) && (ent->client->pers.skill[58] > 7)) { ent->client->silencer_shots -= 1; } else { gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent-g_edicts); gi.WriteByte (MZ_MACHINEGUN | is_silenced); gi.multicast (ent->s.origin, MULTICAST_PVS); } PlayerNoise(ent, start, PNOISE_WEAPON); // if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ent->client->pers.inventory[ent->client->ammo_index]--; ent->client->anim_priority = ANIM_ATTACK; if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) { ent->s.frame = FRAME_crattak1 - (int) (random()+0.25); ent->client->anim_end = FRAME_crattak9; } else { ent->s.frame = FRAME_attack1 - (int) (random()+0.25); ent->client->anim_end = FRAME_attack8; } }
void weapon_phalanx_fire(edict_t *ent) { vec3_t start; vec3_t forward, right, up; vec3_t offset; vec3_t v; int damage; float damage_radius; int radius_damage; if (!ent) { return; } damage = 70 + (int)(random() * 10.0); radius_damage = 120; damage_radius = 120; if (is_quad) { damage *= 4; radius_damage *= 4; } AngleVectors(ent->client->v_angle, forward, right, NULL); VectorScale(forward, -2, ent->client->kick_origin); ent->client->kick_angles[0] = -2; VectorSet(offset, 0, 8, ent->viewheight - 8); P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start); if (ent->client->ps.gunframe == 8) { v[PITCH] = ent->client->v_angle[PITCH]; v[YAW] = ent->client->v_angle[YAW] - 1.5; v[ROLL] = ent->client->v_angle[ROLL]; AngleVectors(v, forward, right, up); radius_damage = 30; damage_radius = 120; fire_plasma(ent, start, forward, damage, 725, damage_radius, radius_damage); if (!((int)dmflags->value & DF_INFINITE_AMMO)) { ent->client->pers.inventory[ent->client->ammo_index]--; } } else { v[PITCH] = ent->client->v_angle[PITCH]; v[YAW] = ent->client->v_angle[YAW] + 1.5; v[ROLL] = ent->client->v_angle[ROLL]; AngleVectors(v, forward, right, up); fire_plasma(ent, start, forward, damage, 725, damage_radius, radius_damage); /* send muzzle flash */ gi.WriteByte(svc_muzzleflash); gi.WriteShort(ent - g_edicts); gi.WriteByte(MZ_PHALANX | is_silenced); gi.multicast(ent->s.origin, MULTICAST_PVS); PlayerNoise(ent, start, PNOISE_WEAPON); } ent->client->ps.gunframe++; }
void Chaingun_Fire (edict_t *ent) { int i; int shots; vec3_t start; vec3_t forward, right, up; float r, u; vec3_t offset; int damage; int kick = 2; if (deathmatch->value) damage = 6; else damage = 8; if (ent->client->ps.gunframe == 5) gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnu1a.wav"), 1, ATTN_IDLE, 0); if ((ent->client->ps.gunframe == 14) && !(ent->client->buttons & BUTTON_ATTACK)) { ent->client->ps.gunframe = 32; ent->client->weapon_sound = 0; return; } else if ((ent->client->ps.gunframe == 21) && (ent->client->buttons & BUTTON_ATTACK) && ent->client->pers.inventory[ent->client->ammo_index]) { ent->client->ps.gunframe = 15; } else { ent->client->ps.gunframe++; } if (ent->client->ps.gunframe == 22) { ent->client->weapon_sound = 0; gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnd1a.wav"), 1, ATTN_IDLE, 0); } else { ent->client->weapon_sound = gi.soundindex("weapons/chngnl1a.wav"); } ent->client->anim_priority = ANIM_ATTACK; if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) { ent->s.frame = FRAME_crattak1 - (ent->client->ps.gunframe & 1); ent->client->anim_end = FRAME_crattak9; } else { ent->s.frame = FRAME_attack1 - (ent->client->ps.gunframe & 1); ent->client->anim_end = FRAME_attack8; } if (ent->client->ps.gunframe <= 9) shots = 1; else if (ent->client->ps.gunframe <= 14) { if (ent->client->buttons & BUTTON_ATTACK) shots = 2; else shots = 1; } else shots = 3; if (ent->client->pers.inventory[ent->client->ammo_index] < shots) shots = ent->client->pers.inventory[ent->client->ammo_index]; if (!shots) { if (level.time >= ent->pain_debounce_time) { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ent->pain_debounce_time = level.time + 1; } NoAmmoWeaponChange (ent); return; } if (is_quad) { damage *= 4; kick *= 4; } for (i=0 ; i<3 ; i++) { ent->client->kick_origin[i] = crandom() * 0.35; ent->client->kick_angles[i] = crandom() * 0.7; } for (i=0 ; i<shots ; i++) { // get start / end positions AngleVectors (ent->client->v_angle, forward, right, up); r = 7 + crandom()*4; u = crandom()*4; VectorSet(offset, 0, r, u + ent->viewheight-8); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_CHAINGUN); } // send muzzle flash gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent-g_edicts); gi.WriteByte ((MZ_CHAINGUN1 + shots - 1) | is_silenced); gi.multicast (ent->s.origin, MULTICAST_PVS); PlayerNoise(ent, start, PNOISE_WEAPON); if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ent->client->pers.inventory[ent->client->ammo_index] -= shots; }
void weapon_bfg_fire(edict_t *ent) { vec3_t offset, start; vec3_t forward, right; int damage; float damage_radius = 1000; if (!ent) { return; } if (deathmatch->value) { damage = 200; } else { damage = 500; } if (ent->client->ps.gunframe == 9) { /* send muzzle flash */ gi.WriteByte(svc_muzzleflash); gi.WriteShort(ent - g_edicts); gi.WriteByte(MZ_BFG | is_silenced); gi.multicast(ent->s.origin, MULTICAST_PVS); ent->client->ps.gunframe++; PlayerNoise(ent, start, PNOISE_WEAPON); return; } /* cells can go down during windup (from power armor hits), so check again and abort firing if we don't have enough now */ if (ent->client->pers.inventory[ent->client->ammo_index] < 50) { ent->client->ps.gunframe++; return; } if (is_quad) { damage *= 4; } AngleVectors(ent->client->v_angle, forward, right, NULL); VectorScale(forward, -2, ent->client->kick_origin); /* make a big pitch kick with an inverse fall */ ent->client->v_dmg_pitch = -40; ent->client->v_dmg_roll = crandom() * 8; ent->client->v_dmg_time = level.time + DAMAGE_TIME; VectorSet(offset, 8, 8, ent->viewheight - 8); P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start); fire_bfg(ent, start, forward, damage, 400, damage_radius); ent->client->ps.gunframe++; PlayerNoise(ent, start, PNOISE_WEAPON); if (!((int)dmflags->value & DF_INFINITE_AMMO)) { ent->client->pers.inventory[ent->client->ammo_index] -= 50; } }
void weapon_ionripper_fire(edict_t *ent) { vec3_t start; vec3_t forward, right; vec3_t offset; vec3_t tempang; int damage; if (!ent) { return; } if (deathmatch->value) { /* tone down for deathmatch */ damage = 30; } else { damage = 50; } if (is_quad) { damage *= 4; } VectorCopy(ent->client->v_angle, tempang); tempang[YAW] += crandom(); AngleVectors(tempang, forward, right, NULL); VectorScale(forward, -3, ent->client->kick_origin); ent->client->kick_angles[0] = -3; VectorSet(offset, 16, 7, ent->viewheight - 8); P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start); fire_ionripper(ent, start, forward, damage, 500, EF_IONRIPPER); /* send muzzle flash */ gi.WriteByte(svc_muzzleflash); gi.WriteShort(ent - g_edicts); gi.WriteByte(MZ_IONRIPPER | is_silenced); gi.multicast(ent->s.origin, MULTICAST_PVS); ent->client->ps.gunframe++; PlayerNoise(ent, start, PNOISE_WEAPON); if (!((int)dmflags->value & DF_INFINITE_AMMO)) { ent->client->pers.inventory[ent->client->ammo_index] -= ent->client->pers.weapon->quantity; } if (ent->client->pers.inventory[ent->client->ammo_index] < 0) { ent->client->pers.inventory[ent->client->ammo_index] = 0; } }
void SpawnLaser (edict_t *ent, int cost, float skill_mult, float delay_mult) { int talentLevel = getTalentLevel(ent, TALENT_RAPID_ASSEMBLY);//Talent: Rapid Assembly float delay; vec3_t forward, right, start, end, offset; trace_t tr; edict_t *grenade, *laser; // get starting position and forward vector AngleVectors (ent->client->v_angle, forward, right, NULL); VectorSet(offset, 0, 8, ent->viewheight-8); P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start); // get end position VectorMA(start, 64, forward, end); tr = gi.trace (start, NULL, NULL, end, ent, MASK_SOLID); // can't build a laser on sky if (tr.surface && (tr.surface->flags & SURF_SKY)) return; if (tr.fraction == 1) { gi.cprintf(ent, PRINT_HIGH, "Too far from wall.\n"); return; } if (NearbyLasers(ent, tr.endpos)) { gi.cprintf(ent, PRINT_HIGH, "Too close to another laser.\n"); return; } if (NearbyProxy(ent, tr.endpos)) { gi.cprintf(ent, PRINT_HIGH, "Too close to a proxy grenade.\n"); return; } laser = G_Spawn(); grenade = G_Spawn(); // create the laser beam laser->monsterinfo.level = ent->myskills.abilities[BUILD_LASER].current_level * skill_mult; laser->dmg = LASER_INITIAL_DAMAGE+LASER_ADDON_DAMAGE*laser->monsterinfo.level; laser->health = LASER_INITIAL_HEALTH+LASER_ADDON_HEALTH*laser->monsterinfo.level; // nerf lasers in CTF and invasion //if (ctf->value || invasion->value) // laser->health *= 0.5; laser->max_health = laser->health; // set beam diameter if (laser->monsterinfo.level >= 10) laser->s.frame = 4; else laser->s.frame = 2; laser->movetype = MOVETYPE_NONE; laser->solid = SOLID_NOT; laser->s.renderfx = RF_BEAM|RF_TRANSLUCENT; laser->s.modelindex = 1; // must be non-zero laser->s.sound = gi.soundindex ("world/laser.wav"); laser->classname = "laser"; laser->owner = laser->activator = ent; // link to player laser->creator = grenade; // link to grenade laser->s.skinnum = 0xf2f2f0f0; // red beam color laser->think = laser_beam_think; laser->nextthink = level.time + LASER_SPAWN_DELAY * delay_mult; VectorCopy(ent->s.origin, laser->s.origin); VectorCopy(tr.endpos, laser->s.old_origin); VectorCopy(tr.endpos, laser->pos1); // beam origin vectoangles(tr.plane.normal, laser->s.angles); gi.linkentity(laser); delay = LASER_TIMEOUT_DELAY+GetRandom(0, (int)(0.5*LASER_TIMEOUT_DELAY)); // laser times out faster in CTF because it's too strong //if (ctf->value || invasion->value) // delay *= 0.5; // create the laser emmitter (grenade) VectorCopy(tr.endpos, grenade->s.origin); vectoangles(tr.plane.normal, grenade->s.angles); grenade->movetype = MOVETYPE_NONE; grenade->clipmask = MASK_SHOT; grenade->solid = SOLID_BBOX; VectorSet(grenade->mins, -3, -3, 0); VectorSet(grenade->maxs, 3, 3, 6); grenade->takedamage = DAMAGE_NO; grenade->s.modelindex = gi.modelindex("models/objects/grenade2/tris.md2"); grenade->activator = ent; // link to player grenade->creator = laser; // link to laser grenade->classname = "emitter"; grenade->mtype = M_LASER;//4.5 grenade->nextthink = level.time+FRAMETIME;//delay; // time before self-destruct //grenade->delay = level.time + delay;//4.4 time before self destruct grenade->think = emitter_think;//laser_remove; grenade->touch = laser_touch;//4.4 gi.linkentity(grenade); // cost is doubled if you are a flyer or cacodemon below skill level 5 if ((ent->mtype == MORPH_FLYER && ent->myskills.abilities[FLYER].current_level < 5) || (ent->mtype == MORPH_CACODEMON && ent->myskills.abilities[CACODEMON].current_level < 5)) cost *= 2; ent->num_lasers++; gi.cprintf(ent, PRINT_HIGH, "Laser built. You have %d/%d lasers.\n", ent->num_lasers, MAX_LASERS); ent->client->pers.inventory[power_cube_index] -= cost; ent->client->ability_delay = level.time + 0.5 * delay_mult; ent->holdtime = level.time + 0.5 * delay_mult; ent->lastsound = level.framenum; }
/* 8===============> FL_think Moving the flashlight <===============8 */ void FL_think (edict_t * self) { vec3_t start, end, endp, offset; vec3_t forward, right, up; vec3_t angles; trace_t tr; int height = 0; /*vec3_t start,end,endp,offset; vec3_t forward,right,up; trace_t tr; */ //AngleVectors (self->owner->client->v_angle, forward, right, up); VectorAdd (self->owner->client->v_angle, self->owner->client->kick_angles, angles); AngleVectors ( /*self->owner->client->v_angle */ angles, forward, right, up); /* VectorSet(offset,24 , 6, self->owner->viewheight-7); G_ProjectSource (self->owner->s.origin, offset, forward, right, start); VectorMA(start,8192,forward,end); tr = gi.trace (start,NULL,NULL, end,self->owner,CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_DEADMONSTER); if (tr.fraction != 1) { VectorMA(tr.endpos,-4,forward,endp); VectorCopy(endp,tr.endpos); } if ((tr.ent->svflags & SVF_MONSTER) || (tr.ent->client)) { if ((tr.ent->takedamage) && (tr.ent != self->owner)) { self->s.skinnum = 1; } } else self->s.skinnum = 0; vectoangles(tr.plane.normal,self->s.angles); VectorCopy(tr.endpos,self->s.origin); gi.linkentity (self); self->nextthink = level.framenum + FRAMEDIV; */ if (self->owner->client->pers.firing_style == ACTION_FIRING_CLASSIC) height = 8; VectorSet (offset, 24, 8, self->owner->viewheight - height); P_ProjectSource (self->owner->client, self->owner->s.origin, offset, forward, right, start); VectorMA (start, 8192, forward, end); PRETRACE (); tr = gi.trace (start, NULL, NULL, end, self->owner, CONTENTS_SOLID | CONTENTS_MONSTER | CONTENTS_DEADMONSTER); POSTTRACE (); if (tr.fraction != 1) { VectorMA (tr.endpos, -4, forward, endp); VectorCopy (endp, tr.endpos); } vectoangles (tr.plane.normal, self->s.angles); VectorCopy (tr.endpos, self->s.origin); gi.linkentity (self); self->nextthink = level.framenum + FRAMEDIV; }
void ParasiteAttack (edict_t *ent) { int damage, kick; vec3_t forward, right, start, end, offset; trace_t tr; if (debuginfo->value) gi.dprintf("%s just called ParasiteAttack()\n", ent->client->pers.userinfo); // terminate attack if (!G_EntIsAlive(ent) || (ent->parasite_frames > PARASITE_MAXFRAMES) || que_typeexists(ent->curses, CURSE_FROZEN)) { parasite_endattack(ent); return; } // calculate starting point AngleVectors (ent->client->v_angle, forward, right, NULL); VectorSet(offset, 0, 7, ent->viewheight-8); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); // do we already have a valid target? if (G_ValidTarget(ent, ent->parasite_target, true) && (entdist(ent, ent->parasite_target) <= PARASITE_RANGE) && infov(ent, ent->parasite_target, 90)) { VectorSubtract(ent->parasite_target->s.origin, start, forward); VectorNormalize(forward); } VectorMA(start, PARASITE_RANGE, forward, end); tr = gi.trace(start, NULL, NULL, end, ent, MASK_SHOT); // did we hit something? if (G_EntIsAlive(tr.ent) && !OnSameTeam(ent, tr.ent)) { if (ent->parasite_frames == 0) { ent->client->pers.inventory[power_cube_index] -= PARASITE_COST; gi.sound (ent, CHAN_AUTO, gi.soundindex("parasite/paratck3.wav"), 1, ATTN_NORM, 0); ent->client->ability_delay = level.time + PARASITE_DELAY; } ent->parasite_target = tr.ent; damage = 2*ent->myskills.abilities[BLOOD_SUCKER].current_level; if (tr.ent->groundentity) kick = -100; else kick = -50; T_Damage(tr.ent, ent, ent, forward, tr.endpos, tr.plane.normal, damage, kick, DAMAGE_NO_ABILITIES, MOD_PARASITE); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_PARASITE_ATTACK); gi.WriteShort(ent-g_edicts); gi.WritePosition(start); gi.WritePosition(tr.endpos); gi.multicast(ent->s.origin, MULTICAST_PVS); ent->parasite_frames++; } else if (ent->parasite_frames) parasite_endattack(ent); }
void weapon_bfg_fire (edict_t *ent) { vec3_t offset, start; vec3_t forward, right; int damage; float damage_radius = 1000; AngleVectors (ent->client->v_angle, forward, right, NULL); VectorScale (forward, -2, ent->client->kick_origin); VectorSet(offset, 8, 8, ent->viewheight-8); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); if(ent->client->ps.gunframe == 9) { ent->flags &= ~FL_BFGMISSFIRE; } if(!(ent->flags & FL_BFGMISSFIRE) && EMPNukeCheck(ent, start)) { ent->flags |= FL_BFGMISSFIRE; gi.sound (ent, CHAN_AUTO, gi.soundindex("items/empnuke/emp_missfire.wav"), 1, ATTN_NORM, 0); } if(ent->flags & FL_BFGMISSFIRE) { ent->client->ps.gunframe++; return; } if (deathmatch->value) damage = 200; else damage = 500; if (ent->client->ps.gunframe == 9) { // send muzzle flash gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent-g_edicts); gi.WriteByte (MZ_BFG | is_silenced); gi.multicast (ent->s.origin, MULTICAST_PVS); ent->client->ps.gunframe++; PlayerNoise(ent, start, PNOISE_WEAPON); return; } // cells can go down during windup (from power armor hits), so // check again and abort firing if we don't have enough now if (ent->client->pers.inventory[ent->client->ammo_index] < 50) { ent->client->ps.gunframe++; return; } if (is_quad) damage *= 4; // make a big pitch kick with an inverse fall ent->client->v_dmg_pitch = -40; ent->client->v_dmg_roll = crandom()*8; ent->client->v_dmg_time = level.time + DAMAGE_TIME; ent->client->ps.gunframe++; if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ent->client->pers.inventory[ent->client->ammo_index] -= 50; fire_bfg (ent, start, forward, damage, 400, damage_radius); PlayerNoise(ent, start, PNOISE_WEAPON); // play quad damage sound playQuadSound(ent); }
void weapon_grenade_fire(edict_t *ent, qboolean held) { vec3_t offset; vec3_t forward, right; vec3_t start; int damage = 125; float timer; int speed; float radius; if (!ent) { return; } radius = damage + 40; if (is_quad) { damage *= 4; } VectorSet(offset, 8, 8, ent->viewheight - 8); AngleVectors(ent->client->v_angle, forward, right, NULL); P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start); timer = ent->client->grenade_time - level.time; speed = GRENADE_MINSPEED + (GRENADE_TIMER - timer) * ((GRENADE_MAXSPEED - GRENADE_MINSPEED) / GRENADE_TIMER); fire_grenade2(ent, start, forward, damage, speed, timer, radius, held); if (!((int)dmflags->value & DF_INFINITE_AMMO)) { ent->client->pers.inventory[ent->client->ammo_index]--; } ent->client->grenade_time = level.time + 1.0; if (ent->deadflag || (ent->s.modelindex != 255)) /* VWep animations screw up corpses */ { return; } if (ent->health <= 0) { return; } if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) { ent->client->anim_priority = ANIM_ATTACK; ent->s.frame = FRAME_crattak1 - 1; ent->client->anim_end = FRAME_crattak3; } else { ent->client->anim_priority = ANIM_REVERSE; ent->s.frame = FRAME_wave08; ent->client->anim_end = FRAME_wave01; } }
void Machinegun_Fire (edict_t *ent) { int i; vec3_t start; vec3_t forward, right; vec3_t angles; int damage = 8; int kick = 2; vec3_t offset; if (!(ent->client->buttons & BUTTON_ATTACK)) { ent->client->machinegun_shots = 0; ent->client->ps.gunframe++; return; } if (ent->client->ps.gunframe == 5) ent->client->ps.gunframe = 4; else ent->client->ps.gunframe = 5; if (ent->client->inventory[ent->client->ammo_index] < 1) { ent->client->ps.gunframe = 6; if (level.framenum >= ent->pain_debounce_framenum) { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ent->pain_debounce_framenum = level.framenum + SECS_TO_FRAMES(1); } NoAmmoWeaponChange (ent); return; } if (is_quad == ent) { damage *= 4; kick *= 4; } for (i=1 ; i<3 ; i++) { ent->client->kick_origin_final[i] = crandom() * 0.35f; ent->client->kick_angles_final[i] = crandom() * 0.7f; } ent->client->kick_origin_final[0] = crandom() * 0.35f; ent->client->kick_angles_final[0] = ent->client->machinegun_shots * -1.5f; ent->client->kick_origin_start = 0; ent->client->kick_origin_end = 0.1f * SERVER_FPS; // get start / end positions VectorAdd (ent->client->v_angle, ent->client->kick_angles_final, angles); AngleVectors (angles, forward, right, NULL); VectorSet(offset, 0, 8, ent->viewheight-8); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_MACHINEGUN); TDM_WeaponFired (ent); gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent-g_edicts); gi.WriteByte (MZ_MACHINEGUN | is_silenced); gi.multicast (ent->s.origin, MULTICAST_PVS); if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ent->client->inventory[ent->client->ammo_index]--; ent->client->anim_priority = ANIM_ATTACK; if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) { ent->s.frame = FRAME_crattak1 - (int) (random()+0.25f); ent->client->anim_end = FRAME_crattak9; } else { ent->s.frame = FRAME_attack1 - (int) (random()+0.25f); ent->client->anim_end = FRAME_attack8; } }
void Cmd_CorpseExplode(edict_t *ent) { int damage, min_dmg, max_dmg, slvl; float fraction, radius; vec3_t start, end, forward, right, offset; trace_t tr; edict_t *e=NULL; if (debuginfo->value) gi.dprintf("DEBUG: %s just called Cmd_CorpseExplode()\n", ent->client->pers.netname); if(ent->myskills.abilities[CORPSE_EXPLODE].disable) return; if (!G_CanUseAbilities(ent, ent->myskills.abilities[CORPSE_EXPLODE].current_level, COST_FOR_CORPSEEXPLODE)) return; slvl = ent->myskills.abilities[CORPSE_EXPLODE].current_level; radius = CORPSE_EXPLOSION_INITIAL_RADIUS + CORPSE_EXPLOSION_ADDON_RADIUS * slvl; // calculate starting position AngleVectors (ent->client->v_angle, forward, right, NULL); VectorSet(offset, 0, 7, ent->viewheight-8); P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start); VectorMA(start, CORPSE_EXPLOSION_MAX_RANGE, forward, end); tr = gi.trace(start, NULL, NULL, end, ent, MASK_SOLID); while ((e = findclosestradius (e, tr.endpos, CORPSE_EXPLOSION_SEARCH_RADIUS)) != NULL) { if (!G_EntExists(e)) continue; if (e->health > 0) continue; if (e->max_health < 1) continue; // kill the corpse T_Damage(e, e, ent, vec3_origin, e->s.origin, vec3_origin, 10000, 0, DAMAGE_NO_PROTECTION, MOD_CORPSEEXPLODE); // inflict damage fraction = 0.1 * GetRandom(5, 10); damage = fraction * e->max_health; // calculate min/max damage range min_dmg = CORPSE_EXPLOSION_INITIAL_DAMAGE + CORPSE_EXPLOSION_ADDON_DAMAGE * slvl; max_dmg = 5 * min_dmg; if (damage < min_dmg) damage = min_dmg; else if (damage > max_dmg) damage = max_dmg; T_RadiusDamage (e, ent, damage, NULL, radius, MOD_CORPSEEXPLODE); //gi.dprintf("fraction %.1f, damage %d, max_health: %d\n", fraction, damage, e->max_health); //Spells like corpse explode shouldn't display 10000 damage, so show the corpse damage instead ent->client->ps.stats[STAT_ID_DAMAGE] = damage; gi.sound(e, CHAN_ITEM, gi.soundindex("spells/corpseexplodecast.wav"), 1, ATTN_NORM, 0); ent->client->pers.inventory[power_cube_index] -= COST_FOR_CORPSEEXPLODE; ent->client->ability_delay = level.time + DELAY_CORPSEEXPLODE; safe_cprintf(ent, PRINT_HIGH, "Corpse exploded for %d damage!\n", damage); //decino: explosion effect gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_GRENADE_EXPLOSION); gi.WritePosition (e->s.origin); gi.multicast (e->s.origin, MULTICAST_PVS); //decino: shoot 6 gibs that deal damage //az: todo, more copypaste. /*for (i = 0; i < 10; i++) { e->s.angles[YAW] += 36; AngleCheck(&e->s.angles[YAW]); AngleVectors(e->s.angles, forward, NULL, up); fire_gib(ent, e->s.origin, forward, dmg, 0, 1000); }*/ // calling entity made a sound, used to alert monsters ent->lastsound = level.framenum; break; } }
void Machinegun_Fire (edict_t *ent) { int i; vec3_t start; vec3_t forward, right; vec3_t angles; int damage = 8; int kick = 2; vec3_t offset; if (!(ent->client->buttons & BUTTON_ATTACK)) { ent->client->machinegun_shots = 0; ent->client->ps.gunframe++; return; } if (ent->client->ps.gunframe == 5) ent->client->ps.gunframe = 4; else ent->client->ps.gunframe = 5; if (ent->client->pers.inventory[ent->client->ammo_index] < 1) { ent->client->ps.gunframe = 6; if (level.time >= ent->pain_debounce_time) { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ent->pain_debounce_time = level.time + 1; } NoAmmoWeaponChange (ent); return; } if (is_quad) { damage *= 4; kick *= 4; } for (i=1 ; i<3 ; i++) { ent->client->kick_origin[i] = crandom() * 0.35; ent->client->kick_angles[i] = crandom() * 0.7; } ent->client->kick_origin[0] = crandom() * 0.35; ent->client->kick_angles[0] = ent->client->machinegun_shots * -1.5; // raise the gun as it is firing if (!deathmatch->value) { ent->client->machinegun_shots++; if (ent->client->machinegun_shots > 9) ent->client->machinegun_shots = 9; } // get start / end positions VectorAdd (ent->client->v_angle, ent->client->kick_angles, angles); AngleVectors (angles, forward, right, NULL); VectorSet(offset, 0, 8, ent->viewheight-8); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_MACHINEGUN); gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent-g_edicts); gi.WriteByte (MZ_MACHINEGUN | is_silenced); gi.multicast (ent->s.origin, MULTICAST_PVS); PlayerNoise(ent, start, PNOISE_WEAPON); if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ent->client->pers.inventory[ent->client->ammo_index]--; ent->client->anim_priority = ANIM_ATTACK; if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) { ent->s.frame = FRAME_crattak1 - (int) (random()+0.25); ent->client->anim_end = FRAME_crattak9; } else { ent->s.frame = FRAME_attack1 - (int) (random()+0.25); ent->client->anim_end = FRAME_attack8; } }
void SpawnMiniSentry (edict_t *ent, int cost, float skill_mult, float delay_mult) { int sentries=0;//3.9 qboolean failed=false; vec3_t offset, forward, right, start, end; edict_t *base; trace_t tr; if (debuginfo->value) gi.dprintf("DEBUG: SpawnMiniSentry()\n"); // create basic ent for sentry base base = G_Spawn(); base->activator = base->creator = ent; VectorCopy(ent->s.angles, base->s.angles); base->s.angles[PITCH] = 0; base->s.angles[ROLL] = 0; base->think = base_createturret; base->nextthink = level.time + SENTRY_BUILD_TIME * delay_mult; base->s.modelindex = gi.modelindex ("models/objects/turret/turret_heavy.md2"); base->solid = SOLID_BBOX; base->movetype = MOVETYPE_TOSS; base->clipmask = MASK_MONSTERSOLID; base->mass = 300; base->health = 500; base->die = base_die; base->classname = "msentrybase"; base->monsterinfo.level = ent->myskills.abilities[BUILD_SENTRY].current_level * skill_mult; base->takedamage = DAMAGE_YES; // need this to let sentry get knocked around VectorSet(base->mins, -32, -32, 0); VectorSet(base->maxs, 32, 32, 12); // calculate starting position AngleVectors (ent->client->v_angle, forward, right, NULL); VectorSet(offset, 0, 7, ent->viewheight-8); P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start); VectorMA(start, 128, forward, end); tr = gi.trace(start, NULL, NULL, end, ent, MASK_SHOT); // base spawned in mid-air if (tr.fraction == 1.0) { base->style = SENTRY_UPRIGHT; } // base spawned below us else if(tr.endpos[2] <= ent->s.origin[2]) { // add the height of the base VectorCopy(tr.endpos, end); end[2] += abs(base->mins[2]); //base->movetype = MOVETYPE_NONE; base->style = SENTRY_UPRIGHT; } // base spawned above us else if (tr.ent && (tr.ent == world || tr.ent->mtype == M_LASERPLATFORM)) { // flip base upside-down base->movetype = MOVETYPE_NONE; base->s.angles[ROLL] += 180; if (base->s.angles[ROLL] < 0) base->s.angles[ROLL] += 360; else if (base->s.angles[ROLL] > 360) base->s.angles[ROLL] -= 360; VectorSet(base->mins, -32, -32, -12); VectorSet(base->maxs, 32, 32, 0); // subtract the height of the base VectorCopy(tr.endpos, end); end[2] -= base->maxs[2]; base->style = SENTRY_FLIPPED; } // make sure the position is valid tr = gi.trace(end, base->mins, base->maxs, end, NULL, MASK_SHOT); if (tr.contents & MASK_SHOT) { G_FreeEdict(base); return; } VectorCopy(tr.endpos, base->s.origin); gi.linkentity(base); gi.sound(base, CHAN_VOICE, gi.soundindex("weapons/repair.wav"), 1, ATTN_NORM, 0); // 3.9 double sentry cost if there are too many sentries in CTF if (ctf->value) { sentries += 2*CTF_GetNumSummonable("Sentry_Gun", ent->teamnum); sentries += CTF_GetNumSummonable("msentrygun", ent->teamnum); if (sentries > MAX_MINISENTRIES) cost *= 2; } // cost is doubled if you are a flyer or cacodemon below skill level 5 if ((ent->mtype == MORPH_FLYER && ent->myskills.abilities[FLYER].current_level < 5) || (ent->mtype == MORPH_CACODEMON && ent->myskills.abilities[CACODEMON].current_level < 5)) cost *= 2; ent->client->pers.inventory[power_cube_index] -= cost; ent->client->ability_delay = level.time + SENTRY_BUILD_TIME * delay_mult; ent->holdtime = level.time + SENTRY_BUILD_TIME * delay_mult; ent->num_sentries++; ent->lastsound = level.framenum; }