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 (!ent) { return; } if (deathmatch->value) { damage = 6; } else { damage = 8; } if (ent->client->ps.gunframe == 5) { PF_StartSound(ent, CHAN_AUTO, SV_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; PF_StartSound(ent, CHAN_AUTO, SV_SoundIndex("weapons/chngnd1a.wav"), 1, ATTN_IDLE, 0); } else { ent->client->weapon_sound = SV_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) { PF_StartSound(ent, CHAN_VOICE, SV_SoundIndex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ent->pain_debounce_time = level.time + 1; } NoAmmoWeaponChange(ent); return; } 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 */ PF_WriteByte(svc_muzzleflash); PF_WriteShort(ent - g_edicts); PF_WriteByte(MZ_CHAINGUN1 + shots - 1); SV_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 fire_rail(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick) { vec3_t from; vec3_t end; trace_t tr; edict_t *ignore; int mask; qboolean water; if (!self) { return; } VectorMA(start, 8192, aimdir, end); VectorCopy(start, from); ignore = self; water = false; mask = MASK_SHOT | CONTENTS_SLIME | CONTENTS_LAVA; while (ignore) { tr = gi.trace(from, NULL, NULL, end, ignore, mask); if (tr.contents & (CONTENTS_SLIME | CONTENTS_LAVA)) { mask &= ~(CONTENTS_SLIME | CONTENTS_LAVA); water = true; } else { if ((tr.ent->svflags & SVF_MONSTER) || (tr.ent->client) || (tr.ent->solid == SOLID_BBOX)) { ignore = tr.ent; } else { ignore = NULL; } if ((tr.ent != self) && (tr.ent->takedamage)) { T_Damage(tr.ent, self, self, aimdir, tr.endpos, tr.plane.normal, damage, kick, 0, MOD_RAILGUN); } else { ignore = NULL; } } VectorCopy(tr.endpos, from); } /* send gun puff / flash */ gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_RAILTRAIL); gi.WritePosition(start); gi.WritePosition(tr.endpos); gi.multicast(self->s.origin, MULTICAST_PHS); if (water) { gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_RAILTRAIL); gi.WritePosition(start); gi.WritePosition(tr.endpos); gi.multicast(tr.endpos, MULTICAST_PHS); } if (self->client) { PlayerNoise(self, tr.endpos, PNOISE_IMPACT); } }
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; // } }
/* ================= P_FallingDamage ================= */ void P_FallingDamage (edict_t *ent) { float delta; int damage; vec3_t dir; if (ent->s.modelindex != 255) return; // not in the player model if (ent->movetype == MOVETYPE_NOCLIP) return; if ((ent->client->oldvelocity[2] < 0) && (ent->velocity[2] > ent->client->oldvelocity[2]) && (!ent->groundentity)) { // if we are airborne and using double-jump, we shouldn't take damage //FIXME: why are we taking fall damage when we are in the air in the first place??? if (ent->v_flags & SFLG_DOUBLEJUMP) return; delta = ent->client->oldvelocity[2]; } else { if (!ent->groundentity) return; delta = ent->velocity[2] - ent->client->oldvelocity[2]; } delta = delta*delta * 0.0001; //K03 Begin if (ent->client->thrusting) return; if (ent->client->hook_state == HOOK_ON) return; //K03 End // never take falling damage if completely underwater if (ent->waterlevel == 3) return; if (ent->waterlevel == 2) delta *= 0.25; if (ent->waterlevel == 1) delta *= 0.5; if (delta < 1) return; if (delta < 15) { if ((ent->client->pers.inventory[ITEM_INDEX(FindItem("Stealth Boots"))] < 1)) { if((ent->myskills.abilities[CLOAK].disable) || (ent->myskills.abilities[CLOAK].current_level < 1)) { // morphed players don't make footsteps if (!ent->mtype) ent->s.event = EV_FOOTSTEP; PlayerNoise(ent, ent->s.origin, PNOISE_SELF); //ponko // if the player is not crouched, then alert monsters of footsteps if (!(ent->client->ps.pmove.pm_flags & PMF_DUCKED)) ent->lastsound = level.framenum; } } return; } ent->client->fall_value = delta*0.5; if (ent->client->fall_value > 40) ent->client->fall_value = 40; ent->client->fall_time = level.time + FALL_TIME; if (delta > 30) { if (ent->health > 0) { if (delta >= 55) ent->s.event = EV_FALLFAR; else ent->s.event = EV_FALL; PlayerNoise(ent, ent->s.origin, PNOISE_SELF); //ponko } ent->pain_debounce_time = level.time; // no normal pain sound damage = (delta-30)/2; if (damage < 1) damage = 1; VectorSet (dir, 0, 0, 1); if (!deathmatch->value || !((int)dmflags->value & DF_NO_FALLING) ) T_Damage (ent, world, world, dir, ent->s.origin, vec3_origin, damage, 0, 0, MOD_FALLING); } else { ent->s.event = EV_FALLSHORT; PlayerNoise(ent, ent->s.origin, PNOISE_SELF); //ponko return; } }
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]--; // play quad damage sound playQuadSound(ent); }
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; } }
//return weapon void Combat_Level0(edict_t *ent,int foundedenemy,int enewep ,float aim,float distance,int skill) { float f; gclient_t *client; zgcl_t *zc; edict_t *target; int mywep,i,j,k; vec3_t v,vv,v1,v2; qboolean mod = false; trace_t rs_trace; client = ent->client; zc = &client->zc; target = zc->first_target; //----------------------------------------------------------------------- //ステータスを反映 //----------------------------------------------------------------------- //チキンは狙いがキツイ============== if(zc->battlemode == FIRE_CHIKEN) aim *= 0.7; //左右に回避======================== if(zc->battlemode & FIRE_SHIFT) { mywep = Get_KindWeapon(client->pers.weapon); Get_AimAngle(ent,aim,distance,mywep); if(--zc->battlesubcnt > 0) { if(ent->groundentity) { if(zc->battlemode & FIRE_SHIFT_R) { zc->moveyaw = ent->s.angles[YAW] + 90; if(zc->moveyaw > 180) zc->moveyaw -= 360; } else { zc->moveyaw = ent->s.angles[YAW] - 90; if(zc->moveyaw < -180) zc->moveyaw += 360; } trace_priority = TRP_MOVEKEEP; //後退処理 } } else { zc->battlemode &= ~FIRE_SHIFT; } } //dodge============================= if(Bot[ent->client->zc.botindex].param[BOP_DODGE] && ent->groundentity && !ent->waterlevel) { AngleVectors (target->client->v_angle, v,NULL, NULL); VectorScale (v, 300, v); VectorSet(vv, 0, 0, target->viewheight-8); VectorAdd(target->s.origin,vv,vv); VectorAdd(vv,v,v); VectorSet(v1, -4, -4,-4); VectorSet(v2, 4, 4, 4); rs_trace = gi.trace(vv,v1,v2,v,target,MASK_SHOT); if(rs_trace.ent == ent) { if(rs_trace.endpos[2] > (ent->s.origin[2] + 4) && random() < 0.4) { client->ps.pmove.pm_flags |= PMF_DUCKED; zc->battleduckcnt = 2 + 8 * random(); } else if(rs_trace.endpos[2] < (ent->s.origin[2] + JumpMax - 24)) { if(zc->route_trace) { if(Bot_Fall(ent,ent->s.origin,0)) trace_priority = TRP_MOVEKEEP;; } else { ent->moveinfo.speed = 0.5; ent->velocity[2] += VEL_BOT_JUMP; gi.sound(ent, CHAN_VOICE, gi.soundindex("*jump1.wav"), 1, ATTN_NORM, 0); PlayerNoise(ent, ent->s.origin, PNOISE_SELF); //pon Set_BotAnim(ent,ANIM_JUMP,FRAME_jump1-1,FRAME_jump6); } } } } //無視して走る======================== if(zc->battlemode & FIRE_IGNORE) { if(--zc->battlecount > 0) { if(zc->first_target != zc->last_target) { zc->battlemode = 0; } else return; } zc->battlemode = 0; } //立ち止まって撃つ準備======================== if(zc->battlemode & FIRE_PRESTAYFIRE) { if(--zc->battlecount > 0) { mywep = Get_KindWeapon(client->pers.weapon); Get_AimAngle(ent,aim,distance,mywep); if(target->client->weaponstate == WEAPON_FIRING && ent->groundentity) ent->client->ps.pmove.pm_flags |= PMF_DUCKED; trace_priority = TRP_ALLKEEP; //動かない return; } if(!(zc->battlemode & FIRE_SHIFT)) zc->battlemode = FIRE_STAYFIRE; //モード遷移 zc->battlecount = 5 + (int)(20 * random()); } //立ち止まって撃つ======================== if(zc->battlemode & FIRE_STAYFIRE) { if(--zc->battlecount > 0) { mywep = Get_KindWeapon(client->pers.weapon); if(1/*mywep == WEAP_BFG*/) CanUsewep(ent,WEAP_BFG); aim *= 0.95; Get_AimAngle(ent,aim,distance,mywep); if(target->client->weaponstate == WEAPON_FIRING && ent->groundentity) { if(mywep == WEAP_BFG) { if(target->s.origin[2] > ent->s.origin[2]) client->ps.pmove.pm_flags |= PMF_DUCKED; } else client->ps.pmove.pm_flags |= PMF_DUCKED; } if(!(zc->battlemode & FIRE_SHIFT)) trace_priority = TRP_ALLKEEP; //動かない if(Bot_traceS(ent,target) || mywep == WEAP_BFG || mywep == WEAP_GRENADELAUNCHER) client->buttons |= BUTTON_ATTACK; return; } zc->battlemode = 0; } //FIRE_RUSH つっこむ======================== if(zc->battlemode & FIRE_RUSH) { if(--zc->battlecount > 0) { mywep = Get_KindWeapon(client->pers.weapon); if(1/*mywep == WEAP_BFG*/) CanUsewep(ent,WEAP_BFG); aim *= 0.95; Get_AimAngle(ent,aim,distance,mywep); if(target->client->weaponstate == WEAPON_FIRING && ent->groundentity) { if(mywep == WEAP_BFG) { if(target->s.origin[2] > ent->s.origin[2]) client->ps.pmove.pm_flags |= PMF_DUCKED; } else client->ps.pmove.pm_flags |= PMF_DUCKED; } trace_priority = TRP_MOVEKEEP; //後退処理 zc->moveyaw = ent->s.angles[YAW]; if(Bot_traceS(ent,target)) client->buttons |= BUTTON_ATTACK; return; } zc->battlemode = 0; } //後退ファイア(爆発回避)======================== if(zc->battlemode & FIRE_EXPAVOID) { if(--zc->battlecount > 0) { mywep = Get_KindWeapon(client->pers.weapon); if(1/*mywep == WEAP_BFG*/) CanUsewep(ent,WEAP_BFG); aim *= 0.95; Get_AimAngle(ent,aim,distance,mywep); if(target->client->weaponstate == WEAPON_FIRING && ent->groundentity) { if(mywep == WEAP_BFG) { if(target->s.origin[2] > ent->s.origin[2]) client->ps.pmove.pm_flags |= PMF_DUCKED; } else client->ps.pmove.pm_flags |= PMF_DUCKED; } trace_priority = TRP_MOVEKEEP; //後退処理 zc->moveyaw = ent->s.angles[YAW] + 180; if(zc->moveyaw > 180) zc->moveyaw -= 360; if(Bot_traceS(ent,target) || mywep == WEAP_BFG || mywep == WEAP_GRENADELAUNCHER) client->buttons |= BUTTON_ATTACK; return; } zc->battlemode = 0; } //BFGファイア(爆発回避)======================== if(zc->battlemode & FIRE_BFG) { if(--zc->battlecount > 0) { mywep = Get_KindWeapon(client->pers.weapon); if(1/*mywep == WEAP_BFG*/) CanUsewep(ent,WEAP_BFG); aim *= 0.95; Get_AimAngle(ent,aim,distance,mywep); if(target->client->weaponstate == WEAPON_FIRING && ent->groundentity) { if(1/*mywep == WEAP_BFG*/) { if(target->s.origin[2] > ent->s.origin[2]) client->ps.pmove.pm_flags |= PMF_DUCKED; } else client->ps.pmove.pm_flags |= PMF_DUCKED; } trace_priority = TRP_ANGLEKEEP; //後退処理 if(Bot_traceS(ent,target) || mywep == WEAP_BFG || mywep == WEAP_GRENADELAUNCHER) client->buttons |= BUTTON_ATTACK; return; } zc->battlemode = 0; } //撃って避難======================== if(zc->battlemode & FIRE_REFUGE) { if(--zc->battlecount > 0) { mywep = Get_KindWeapon(client->pers.weapon); //CanUsewep(ent,WEAP_BFG); aim *= 0.95; Get_AimAngle(ent,aim,distance,mywep); if(target->client->weaponstate == WEAPON_FIRING && ent->groundentity) { if(mywep == WEAP_BFG) { if(target->s.origin[2] > ent->s.origin[2]) client->ps.pmove.pm_flags |= PMF_DUCKED; } else client->ps.pmove.pm_flags |= PMF_DUCKED; } trace_priority = TRP_ANGLEKEEP; //動かない // trace_priority = TRP_ALLKEEP; //動かない if(Bot_traceS(ent,target) || mywep == WEAP_BFG || mywep == WEAP_GRENADELAUNCHER) client->buttons |= BUTTON_ATTACK; return; } zc->battlemode = 0; zc->routeindex -= 2; } if(!(client->zc.zccmbstt & CTS_ENEM_NSEE) && (zc->zcstate & STS_WAITSMASK2) && (target->s.origin[2] - ent->s.origin[2]) < -300) { if(k = CanUsewep(ent,WEAP_GRENADELAUNCHER)) { mywep = Get_KindWeapon(client->pers.weapon); Get_AimAngle(ent,aim,distance,mywep); if((target->client->weaponstate == WEAPON_FIRING && ent->groundentity) || (zc->zcstate & STS_WAITSMASK2)) ent->client->ps.pmove.pm_flags |= PMF_DUCKED; client->buttons |= BUTTON_ATTACK; trace_priority = TRP_ANGLEKEEP; return; } if(k = CanUsewep(ent,WEAP_GRENADES)) { mywep = Get_KindWeapon(client->pers.weapon); Get_AimAngle(ent,aim,distance,mywep); if(target->client->weaponstate == WEAPON_FIRING && ent->groundentity) ent->client->ps.pmove.pm_flags |= PMF_DUCKED; if(ent->client->weaponstate == WEAPON_READY ) client->buttons |= BUTTON_ATTACK; trace_priority = TRP_ANGLEKEEP; return; } } //----------------------------------------------------------------------- //特殊ファイアリング //----------------------------------------------------------------------- mywep = Get_KindWeapon(client->pers.weapon); //左右回避セット======================== if(!(zc->battlemode & FIRE_SHIFT) && skill > (random() * skill) /*&& distance < 250*/ && (30 * random()) < Bot[zc->botindex].param[BOP_OFFENCE]) { k = false; if(zc->route_trace && enewep != WEAP_RAILGUN) { for(i = zc->routeindex;i < (zc->routeindex + 10);i++) { if(i >= CurrentIndex) break; if(Route[i].state == GRS_ITEMS) { if(Route[i].ent->solid == SOLID_TRIGGER) { k = true; break; } } } } if(!k) { Get_AimAngle(ent,aim,distance,mywep); f =target->s.angles[YAW] - ent->s.angles[YAW]; if(f > 180) { f = -(360 - f); } if( f < -180) { f = -(f + 360); } //俺をみている!! if(f <= -160) { zc->battlemode |= FIRE_SHIFT_L; zc->battlesubcnt = 5 + (int)(16 * random()); } else if(f >= 160) { zc->battlemode |= FIRE_SHIFT_R; zc->battlesubcnt = 5 + (int)(16 * random()); } } } //敵がペンタをとっている======================== if((FFlg[skill] & FIRE_AVOIDINV) && target->client->invincible_framenum > level.framenum) { // mywep = Get_KindWeapon(client->pers.weapon); Get_AimAngle(ent,aim,distance,mywep); trace_priority = TRP_MOVEKEEP; //後退処理 zc->moveyaw = ent->s.angles[YAW] + 180; if(zc->moveyaw > 180) zc->moveyaw -= 360; return; } //Quad時の処理================================= if((FFlg[skill] & FIRE_QUADUSE) && (ent->client->quad_framenum > level.framenum) && distance < 300) { j = false; if(enewep < WEAP_MACHINEGUN || enewep == WEAP_GRENADES) j = true; //Hyper Blaster if(k = CanUsewep(ent,WEAP_HYPERBLASTER)) { mywep = Get_KindWeapon(client->pers.weapon); Get_AimAngle(ent,aim,distance,mywep); client->buttons |= BUTTON_ATTACK; trace_priority = TRP_ANGLEKEEP; if(j) { zc->battlemode |= FIRE_RUSH; zc->battlecount = 8 + (int)(10 * random()); } return; } //Chain Gun if(k = CanUsewep(ent,WEAP_CHAINGUN)) { mywep = Get_KindWeapon(client->pers.weapon); Get_AimAngle(ent,aim,distance,mywep); client->buttons |= BUTTON_ATTACK; trace_priority = TRP_ANGLEKEEP; if(j) { zc->battlemode |= FIRE_RUSH; zc->battlecount = 8 + (int)(10 * random()); } return; } //Machine Gun if(k = CanUsewep(ent,WEAP_MACHINEGUN)) { mywep = Get_KindWeapon(client->pers.weapon); Get_AimAngle(ent,aim,distance,mywep); client->buttons |= BUTTON_ATTACK; trace_priority = TRP_ANGLEKEEP; if(j) { zc->battlemode |= FIRE_RUSH; zc->battlecount = 8 + (int)(10 * random()); } return; } //S-Shotgun if(k = CanUsewep(ent,WEAP_SUPERSHOTGUN)) { mywep = Get_KindWeapon(client->pers.weapon); Get_AimAngle(ent,aim,distance,mywep); client->buttons |= BUTTON_ATTACK; trace_priority = TRP_ANGLEKEEP; if(j) { zc->battlemode |= FIRE_RUSH; zc->battlecount = 8 + (int)(10 * random()); } return; } } //撃って逃げる処理================================= if((FFlg[skill] & FIRE_REFUGE) && zc->battlemode == 0 && zc->route_trace && zc->routeindex > 1 ) { j = false; if(enewep >= WEAP_CHAINGUN && enewep != WEAP_GRENADES) j = true; Get_RouteOrigin(zc->routeindex - 2,v); if(fabs(v[2] - ent->s.origin[2]) < JumpMax && j) { mywep = Get_KindWeapon(client->pers.weapon); if(mywep == WEAP_GRENADELAUNCHER || mywep == WEAP_ROCKETLAUNCHER ) { zc->battlemode |= FIRE_REFUGE; //モード遷移 zc->battlecount = 8 + (int)(10 * random()); trace_priority = TRP_ALLKEEP; return; } } } //トレース中以外のときにグルグルを防ぐ================================= if(!zc->route_trace && distance < 100) { zc->battlemode |= FIRE_EXPAVOID; //モード遷移 zc->battlecount = 4 + (int)(8 * random()); trace_priority = TRP_ALLKEEP; } //----------------------------------------------------------------------- //プライオリティ //----------------------------------------------------------------------- //BFG if(distance > 200) { if(B_UseBfg(ent,target,enewep,aim,distance,skill)) goto FIRED; } for(i = 0;i < 3;i++) { mywep = Get_KindWeapon(client->pers.weapon); if(i == 0 && zc->secwep_selected) continue; //try to select secondary weapon if(i == 0 && zc->secwep_selected) i = 1; else if(i == 0 && foundedenemy < 3 && target->health < 50 && !zc->secwep_selected && ent->health >= 50) { if((9 * random()) < Bot[zc->botindex].param[BOP_COMBATSKILL]) { zc->secwep_selected = 2; i = 1; } } if(i == 2) { if(zc->secwep_selected) { zc->secwep_selected = 0; j = 0; } else break; } else j = i; if(distance > 100 && (mywep == WEAP_BFG || random() < 0.5)) { if(B_UseBfg(ent,target,enewep,aim,distance,skill)) goto FIRED; } switch(Bot[zc->botindex].param[BOP_PRIWEP + j]) { case WEAP_RAILGUN: if(distance > 1 || voosh->value > 0 ) { if(B_UseRailgun(ent,target,enewep,aim,distance,skill)|| voosh->value) goto FIRED; } break; case WEAP_BFG: if(distance > 100) { if(B_UseBfg(ent,target,enewep,aim,distance,skill)) goto FIRED; } break; case WEAP_HYPERBLASTER: if(distance < 1200) { if(B_UseHyperBlaster(ent,target,enewep,aim,distance,skill)) goto FIRED; } break; case WEAP_ROCKETLAUNCHER: if(distance > 100 && distance < 1200/*|| mywep == WEAP_ROCKETLAUNCHER*/) { if(B_UseRocket(ent,target,enewep,aim,distance,skill)) goto FIRED; } break; case WEAP_GRENADELAUNCHER: if(distance > 100 && distance < 400 && (target->s.origin[2] - ent->s.origin[2]) < 200) { if(B_UseGrenadeLauncher(ent,target,enewep,aim,distance,skill)) goto FIRED; } break; case WEAP_CHAINGUN: case WEAP_MACHINEGUN: if(distance < 1200) { if(B_UseChainGun(ent,target,enewep,aim,distance,skill)) goto FIRED; } if(distance < 1200) { if(B_UseMachineGun(ent,target,enewep,aim,distance,skill)) goto FIRED; } break; case WEAP_SUPERSHOTGUN: case WEAP_SHOTGUN: if(distance < 1200) { if(B_UseSuperShotgun(ent,target,enewep,aim,distance,skill)) goto FIRED; } if(distance < 1200) { if(B_UseShotgun(ent,target,enewep,aim,distance,skill)) goto FIRED; } case WEAP_GRENADES: if(distance < 1200) { if(B_UseHandGrenade(ent,target,enewep,aim,distance,skill)) goto FIRED; } break; default: break; } } //----------------------------------------------------------------------- //通常ファイアリング //----------------------------------------------------------------------- zc->secwep_selected = 0; //BFG if(distance > 200) { if(B_UseBfg(ent,target,enewep,aim,distance,skill)) goto FIRED; } //Hyper Blaster if(distance < 1200) { if(B_UseHyperBlaster(ent,target,enewep,aim,distance,skill)) goto FIRED; } //Rocket if((distance > 100 && distance < 1200)/*|| mywep == WEAP_ROCKETLAUNCHER*/) { if(B_UseRocket(ent,target,enewep,aim,distance,skill)) goto FIRED; } //Railgun if(distance > 1200 || voosh->value) { if(B_UseRailgun(ent,target,enewep,aim,distance,skill)||voosh->value) goto FIRED; } //Grenade Launcher if(distance > 100 && distance < 400 && (target->s.origin[2] - ent->s.origin[2]) < 200) { if(B_UseGrenadeLauncher(ent,target,enewep,aim,distance,skill)) goto FIRED; } //Chain Gun if(distance < 1200) { if(B_UseChainGun(ent,target,enewep,aim,distance,skill)) goto FIRED; } //Machine Gun if(distance < 1200) { if(B_UseMachineGun(ent,target,enewep,aim,distance,skill)) goto FIRED; } //S-Shotgun if(distance < 1200) { if(B_UseSuperShotgun(ent,target,enewep,aim,distance,skill)) goto FIRED; } if((FFlg[skill] & FIRE_IGNORE) && distance > 400 && ent->groundentity && !(zc->zcstate & STS_WAITSMASK)) { zc->battlemode = FIRE_IGNORE; zc->battlecount = 5 + (int)(10 * random()); } //Shotgun if(distance < 1200) { if(B_UseShotgun(ent,target,enewep,aim,distance,skill)) goto FIRED; } //Hand Grenade if(distance < 400) { if(B_UseHandGrenade(ent,target,enewep,aim,distance,skill)) goto FIRED; } //Blaster if(distance < 1200) { if(B_UseBlaster(ent,target,enewep,aim,distance,skill)) goto FIRED; } VectorSubtract(zc->vtemp,ent->s.origin,v); ent->s.angles[YAW] = Get_yaw(v); ent->s.angles[PITCH] = Get_pitch(v); trace_priority = TRP_ANGLEKEEP; return; FIRED: if(zc->secwep_selected == 2) zc->secwep_selected = 1; //チキンやろう======================== if(zc->battlemode == FIRE_CHIKEN) { if(--zc->battlesubcnt > 0 && ent->groundentity && ent->waterlevel < 2) { f =target->s.angles[YAW] - ent->s.angles[YAW]; if(f > 180) { f = -(360 - f); } if( f < -180) { f = -(f + 360); } if(fabs(f) >= 150) { zc->battlemode = 0; } else { if(client->weaponstate != WEAPON_READY && target->s.origin[2] < ent->s.origin[2] ) { if(mywep == WEAP_ROCKETLAUNCHER || mywep == WEAP_GRENADELAUNCHER || mywep == WEAP_RAILGUN) client->ps.pmove.pm_flags |= PMF_DUCKED; else if(Bot[zc->botindex].param[BOP_COMBATSKILL] >= 7) { if(mywep == WEAP_SHOTGUN || mywep == WEAP_SUPERSHOTGUN || mywep == WEAP_BLASTER) client->ps.pmove.pm_flags |= PMF_DUCKED; } } trace_priority = TRP_ALLKEEP; } return; } else zc->battlemode = 0; } else if(zc->battlemode == 0 && distance > 200 && ent->groundentity && ent->waterlevel < 2 && (9 * random()) > Bot[zc->botindex].param[BOP_OFFENCE]) { mywep = Get_KindWeapon(client->pers.weapon); if(mywep > WEAP_BLASTER && target->client->zc.first_target != ent) { f =target->s.angles[YAW] - ent->s.angles[YAW]; if(f > 180) { f = -(360 - f); } if( f < -180) { f = -(f + 360); } if(fabs(f) < 150) { zc->battlemode = FIRE_CHIKEN; zc->battlesubcnt = 5 + (int)(random() * 8); trace_priority = TRP_ALLKEEP; } } } }
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"); } 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; } if(EMPNukeCheck(ent, ent->s.origin)) { gi.sound (ent, CHAN_AUTO, gi.soundindex("items/empnuke/emp_missfire.wav"), 1, ATTN_NORM, 0); return; } if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ent->client->pers.inventory[ent->client->ammo_index] -= shots; 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); // play quad damage sound playQuadSound(ent); }
/* ================= fire_bow ================= */ void arrow_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) { qboolean damageSuccess = false; int r; if (other == self->owner) return; if (surf && (surf->flags & SURF_SKY)) { G_FreeEdict (self); return; } if (self->owner->client) PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT); if (other->takedamage) { r = rand() % 100; if (r < self->owner->client->pers.marksman * 2) // Calculate damageSuccess based on marksman skill { damageSuccess = true; // The hit will successfully do damage if (self->owner->client->pers.marksman < 100) // If the marksman skill is less than the skill cap { self->owner->client->pers.marksman = self->owner->client->pers.marksman + 0.01; // Add progress to the skill if ((self->owner->client->pers.marksman - (int)self->owner->client->pers.marksman) * 100 >= (int)self->owner->client->pers.marksman - 25) // If the skill levels { self->owner->client->pers.marksman = self->owner->client->pers.marksman + (1 - (self->owner->client->pers.marksman - (int)self->owner->client->pers.marksman)); // Increase the skill to the next level gi.centerprintf(self->owner, "Your Marksman Skill Has Increased To %i\n", (int)self->owner->client->pers.marksman); // Print that the player's skill has increased gi.sound(self->owner, CHAN_AUTO, gi.soundindex("morrowind/skill.wav"), 1, ATTN_NORM, 0); // Play skill up sound } } } if (damageSuccess == true) { T_Damage(other, self, self->owner, self->velocity, self->s.origin, plane->normal, self->dmg, 1, DAMAGE_ENERGY, MOD_BOW); gi.sound(other, CHAN_AUTO, gi.soundindex("morrowind/BodyHit.wav"), 1, ATTN_NORM, 0); /* gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_BLOOD); gi.WritePosition (self->s.origin); gi.multicast (self->s.origin, MULTICAST_PVS); */ } else gi.sound(other, CHAN_AUTO, gi.soundindex("morrowind/Miss.wav"), 1, ATTN_NORM, 0); } else { gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_SPARKS); gi.WritePosition (self->s.origin); if (!plane) gi.WriteDir (vec3_origin); else gi.WriteDir (plane->normal); gi.multicast (self->s.origin, MULTICAST_PVS); } G_FreeEdict (self); }
//------------------------------------------------------------ qboolean B_UseRocket(edict_t *ent,edict_t *target,int enewep,float aim,float distance,int skill) { int k,mywep; zgcl_t *zc; gclient_t *client; client = ent->client; zc = &client->zc; if(k = CanUsewep(ent,WEAP_ROCKETLAUNCHER)) { mywep = Get_KindWeapon(client->pers.weapon); Get_AimAngle(ent,aim,distance,mywep); if(trace_priority < TRP_ANGLEKEEP) trace_priority = TRP_ANGLEKEEP; if((FFlg[skill] & FIRE_PRESTAYFIRE) && ((distance > 500 && random() < 0.1) || fabs(ent->s.angles[PITCH]) > 45 ) && Bot_traceS(ent,target) && (enewep <= WEAP_MACHINEGUN || enewep == WEAP_GRENADES)) { if(ent->groundentity || zc->waterstate) { zc->battlemode |= FIRE_PRESTAYFIRE; zc->battlecount = 2 + (int)(6 * random()); trace_priority = TRP_ALLKEEP; return true; } } if((FFlg[skill] & FIRE_JUMPROC) && random() < 0.3 && (target->s.origin[2] - ent->s.origin[2]) < JumpMax && !(client->ps.pmove.pm_flags && PMF_DUCKED)) { if(ent->groundentity && !ent->waterlevel <= 1) { if(zc->route_trace) { if(Bot_Fall(ent,ent->s.origin,0)) { trace_priority = TRP_ALLKEEP; if(Bot_traceS(ent,target)) client->buttons |= BUTTON_ATTACK; return true; } } else { ent->moveinfo.speed = 0; ent->velocity[2] += VEL_BOT_JUMP; gi.sound(ent, CHAN_VOICE, gi.soundindex("*jump1.wav"), 1, ATTN_NORM, 0); PlayerNoise(ent, ent->s.origin, PNOISE_SELF); //pon Set_BotAnim(ent,ANIM_JUMP,FRAME_jump1-1,FRAME_jump6); trace_priority = TRP_ALLKEEP; if(Bot_traceS(ent,target)) client->buttons |= BUTTON_ATTACK; return true; } } } else if((FFlg[skill] & FIRE_EXPAVOID) && distance < 300 && random() < 0.5 && Bot_traceS(ent,target)) { if(ent->groundentity || zc->waterstate) { zc->battlemode |= FIRE_EXPAVOID; zc->battlecount = 4 + (int)(6 * random()); trace_priority = TRP_ALLKEEP; return true; } } if(Bot_traceS(ent,target)) client->buttons |= BUTTON_ATTACK; return true; } return false; }
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 bfg_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) { if (!self || !other) { G_FreeEdict(self); return; } if (other == self->owner) { return; } if (surf && (surf->flags & SURF_SKY)) { G_FreeEdict(self); return; } if (self->owner && self->owner->client) { PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT); } /* core explosion - prevents firing it into the wall/floor */ if (other->takedamage) { if (plane) { T_Damage(other, self, self->owner, self->velocity, self->s.origin, plane->normal, 200, 0, 0, MOD_BFG_BLAST); } else { T_Damage(other, self, self->owner, self->velocity, self->s.origin, vec3_origin, 200, 0, 0, MOD_BFG_BLAST); } } T_RadiusDamage(self, self->owner, 200, other, 100, MOD_BFG_BLAST); gi.sound(self, CHAN_VOICE, gi.soundindex( "weapons/bfg__x1b.wav"), 1, ATTN_NORM, 0); self->solid = SOLID_NOT; self->touch = NULL; VectorMA(self->s.origin, -1 * FRAMETIME, self->velocity, self->s.origin); VectorClear(self->velocity); self->s.modelindex = gi.modelindex("sprites/s_bfg3.sp2"); self->s.frame = 0; self->s.sound = 0; self->s.effects &= ~EF_ANIM_ALLFAST; self->think = bfg_explode; self->nextthink = level.time + FRAMETIME; self->enemy = other; gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_BFG_BIGEXPLOSION); gi.WritePosition(self->s.origin); gi.multicast(self->s.origin, MULTICAST_PVS); }
/* ================= fire_blaster Fires a single blaster bolt. Used by the blaster and hyper blaster. ================= */ void blaster_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) { int mod; if (!self || !other) { G_FreeEdict(self); return; } if (other == self->owner) { return; } if (surf && (surf->flags & SURF_SKY)) { G_FreeEdict(self); return; } if (self->owner->client) { PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT); } if (other->takedamage) { if (self->spawnflags & 1) { mod = MOD_HYPERBLASTER; } else { mod = MOD_BLASTER; } T_Damage(other, self, self->owner, self->velocity, self->s.origin, plane->normal, self->dmg, 1, DAMAGE_ENERGY, mod); } else { gi.WriteByte (svc_temp_entity); // RAFAEL if (self->s.effects & EF_BLUEHYPERBLASTER) // Knightmare- this was checking bit TE_BLUEHYPERBLASTER gi.WriteByte (TE_BLUEHYPERBLASTER); // Knightmare- TE_BLUEHYPERBLASTER is broken (parse error) in most Q2 engines else gi.WriteByte (TE_BLASTER); gi.WritePosition(self->s.origin); if (!plane) { gi.WriteDir(vec3_origin); } else { gi.WriteDir(plane->normal); } gi.multicast(self->s.origin, MULTICAST_PVS); } G_FreeEdict(self); }
/* ============== ClientThink This will be called once for each client frame, which will usually be a couple times for each server frame. ============== */ void ClientThink (edict_t *ent, usercmd_t *ucmd) { gclient_t *client; edict_t *other; int i, j; pmove_t pm; level.current_entity = ent; client = ent->client; if (level.intermissiontime) { client->ps.pmove.pm_type = PM_FREEZE; // can exit intermission after five seconds if (level.time > level.intermissiontime + 5.0 && (ucmd->buttons & BUTTON_ANY) ) level.exitintermission = true; return; } pm_passent = ent; if (ent->client->chase_target) { client->resp.cmd_angles[0] = SHORT2ANGLE(ucmd->angles[0]); client->resp.cmd_angles[1] = SHORT2ANGLE(ucmd->angles[1]); client->resp.cmd_angles[2] = SHORT2ANGLE(ucmd->angles[2]); } else { // set up for pmove memset (&pm, 0, sizeof(pm)); if (ent->movetype == MOVETYPE_NOCLIP) client->ps.pmove.pm_type = PM_SPECTATOR; else if (ent->s.modelindex != 255) client->ps.pmove.pm_type = PM_GIB; else if (ent->deadflag) client->ps.pmove.pm_type = PM_DEAD; else client->ps.pmove.pm_type = PM_NORMAL; client->ps.pmove.gravity = 0; pm.s = client->ps.pmove; for (i=0 ; i<3 ; i++) { pm.s.origin[i] = ent->s.origin[i]*8; pm.s.velocity[i] = ent->velocity[i]*8; } if (memcmp(&client->old_pmove, &pm.s, sizeof(pm.s))) { pm.snapinitial = true; // gi.dprintf ("pmove changed!\n"); } pm.cmd = *ucmd; pm.trace = PM_trace; // adds default parms pm.pointcontents = gi.pointcontents; // perform a pmove gi.Pmove (&pm); // save results of pmove client->ps.pmove = pm.s; client->old_pmove = pm.s; for (i=0 ; i<3 ; i++) { ent->s.origin[i] = pm.s.origin[i]*0.125; ent->velocity[i] = pm.s.velocity[i]*0.125; } VectorCopy (pm.mins, ent->mins); VectorCopy (pm.maxs, ent->maxs); client->resp.cmd_angles[0] = SHORT2ANGLE(ucmd->angles[0]); client->resp.cmd_angles[1] = SHORT2ANGLE(ucmd->angles[1]); client->resp.cmd_angles[2] = SHORT2ANGLE(ucmd->angles[2]); if (ent->groundentity && !pm.groundentity && (pm.cmd.upmove >= 10) && (pm.waterlevel == 0)) { gi.sound(ent, CHAN_VOICE, gi.soundindex("*jump1.wav"), 1, ATTN_NORM, 0); PlayerNoise(ent, ent->s.origin, PNOISE_SELF); } ent->viewheight = pm.viewheight; ent->waterlevel = pm.waterlevel; ent->watertype = pm.watertype; ent->groundentity = pm.groundentity; if (pm.groundentity) ent->groundentity_linkcount = pm.groundentity->linkcount; if (ent->deadflag) { client->ps.viewangles[ROLL] = 40; client->ps.viewangles[PITCH] = -15; client->ps.viewangles[YAW] = client->killer_yaw; } else { VectorCopy (pm.viewangles, client->v_angle); VectorCopy (pm.viewangles, client->ps.viewangles); } gi.linkentity (ent); if (ent->movetype != MOVETYPE_NOCLIP) G_TouchTriggers (ent); // touch other objects for (i=0 ; i<pm.numtouch ; i++) { other = pm.touchents[i]; for (j=0 ; j<i ; j++) if (pm.touchents[j] == other) break; if (j != i) continue; // duplicated if (!other->touch) continue; other->touch (other, ent, NULL, NULL); } } client->oldbuttons = client->buttons; client->buttons = ucmd->buttons; client->latched_buttons |= client->buttons & ~client->oldbuttons; // save light level the player is standing on for // monster sighting AI ent->light_level = ucmd->lightlevel; // fire weapon from final position if needed if (client->latched_buttons & BUTTON_ATTACK) { if (client->resp.spectator) { client->latched_buttons = 0; if (client->chase_target) { client->chase_target = NULL; client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION; } else GetChaseTarget(ent); } else if (!client->weapon_thunk) { client->weapon_thunk = true; Think_Weapon (ent); } } if (client->resp.spectator) { if (ucmd->upmove >= 10) { if (!(client->ps.pmove.pm_flags & PMF_JUMP_HELD)) { client->ps.pmove.pm_flags |= PMF_JUMP_HELD; if (client->chase_target) ChaseNext(ent); else GetChaseTarget(ent); } } else client->ps.pmove.pm_flags &= ~PMF_JUMP_HELD; } // update chase cam if being followed for (i = 1; i <= maxclients->value; i++) { other = g_edicts + i; if (other->inuse && other->client->chase_target == ent) UpdateChaseCam(other); } }
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; } }
/* ============= P_WorldEffects ============= */ void P_WorldEffects (void) { qboolean breather; qboolean envirosuit; int waterlevel, old_waterlevel; if (current_player->movetype == MOVETYPE_NOCLIP) { current_player->air_finished = level.time + 12; // don't need air return; } waterlevel = current_player->waterlevel; old_waterlevel = current_client->old_waterlevel; current_client->old_waterlevel = waterlevel; breather = current_client->breather_framenum > level.framenum; envirosuit = current_client->enviro_framenum > level.framenum; // // if just entered a water volume, play a sound // if (!old_waterlevel && waterlevel) { PlayerNoise (current_player, current_player->s.origin, PNOISE_SELF); if (current_player->watertype & CONTENTS_LAVA) gi.sound (current_player, CHAN_BODY, gi.soundindex ("player/lava_in.wav"), 1, ATTN_NORM, 0); else if (current_player->watertype & CONTENTS_SLIME) gi.sound (current_player, CHAN_BODY, gi.soundindex ("player/watr_in.wav"), 1, ATTN_NORM, 0); else if (current_player->watertype & CONTENTS_WATER) gi.sound (current_player, CHAN_BODY, gi.soundindex ("player/watr_in.wav"), 1, ATTN_NORM, 0); current_player->flags |= FL_INWATER; // clear damage_debounce, so the pain sound will play immediately current_player->damage_debounce_time = level.time - 1; } // // if just completely exited a water volume, play a sound // if (old_waterlevel && !waterlevel) { PlayerNoise (current_player, current_player->s.origin, PNOISE_SELF); gi.sound (current_player, CHAN_BODY, gi.soundindex ("player/watr_out.wav"), 1, ATTN_NORM, 0); current_player->flags &= ~FL_INWATER; } // // check for head just going under water // if (old_waterlevel != 3 && waterlevel == 3) { gi.sound (current_player, CHAN_BODY, gi.soundindex ("player/watr_un.wav"), 1, ATTN_NORM, 0); } // // check for head just coming out of water // if (old_waterlevel == 3 && waterlevel != 3) { if (current_player->air_finished < level.time) { // gasp for air gi.sound (current_player, CHAN_VOICE, gi.soundindex ("player/gasp1.wav"), 1, ATTN_NORM, 0); PlayerNoise (current_player, current_player->s.origin, PNOISE_SELF); } else if (current_player->air_finished < level.time + 11) { // just break surface gi.sound (current_player, CHAN_VOICE, gi.soundindex ("player/gasp2.wav"), 1, ATTN_NORM, 0); } } // // check for drowning // if (waterlevel == 3) { // breather or envirosuit give air if (breather || envirosuit) { current_player->air_finished = level.time + 10; if (((int)(current_client->breather_framenum - level.framenum) % 25) == 0) { if (!current_client->breather_sound) gi.sound (current_player, CHAN_AUTO, gi.soundindex("player/u_breath1.wav"), 1, ATTN_NORM, 0); else gi.sound (current_player, CHAN_AUTO, gi.soundindex("player/u_breath2.wav"), 1, ATTN_NORM, 0); current_client->breather_sound ^= 1; PlayerNoise (current_player, current_player->s.origin, PNOISE_SELF); //FIXME: release a bubble? } } // if out of air, start drowning if (current_player->air_finished < level.time) { // drown! if (current_player->client->next_drown_time < level.time && current_player->health > 0) { current_player->client->next_drown_time = level.time + 1; // take more damage the longer underwater current_player->dmg += 2; if (current_player->dmg > 15) current_player->dmg = 15; // play a gurp sound instead of a normal pain sound if (current_player->health <= current_player->dmg) gi.sound (current_player, CHAN_VOICE, gi.soundindex ("player/drown1.wav"), 1, ATTN_NORM, 0); else if (rand () & 1) gi.sound (current_player, CHAN_VOICE, gi.soundindex ("*gurp1.wav"), 1, ATTN_NORM, 0); else gi.sound (current_player, CHAN_VOICE, gi.soundindex ("*gurp2.wav"), 1, ATTN_NORM, 0); current_player->pain_debounce_time = level.time; T_Damage (current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, current_player->dmg, 0, DAMAGE_NO_ARMOR, MOD_WATER); } } } else { current_player->air_finished = level.time + 12; current_player->dmg = 2; } // // check for sizzle damage // if (waterlevel && (current_player->watertype & (CONTENTS_LAVA | CONTENTS_SLIME))) { if (current_player->watertype & CONTENTS_LAVA) { if (current_player->health > 0 && current_player->pain_debounce_time <= level.time && current_client->invincible_framenum < level.framenum) { if (rand () & 1) gi.sound (current_player, CHAN_VOICE, gi.soundindex ("player/burn1.wav"), 1, ATTN_NORM, 0); else gi.sound (current_player, CHAN_VOICE, gi.soundindex ("player/burn2.wav"), 1, ATTN_NORM, 0); current_player->pain_debounce_time = level.time + 1; } if (envirosuit) // take 1/3 damage with envirosuit T_Damage (current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, 1 * waterlevel, 0, 0, MOD_LAVA); else T_Damage (current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, 3 * waterlevel, 0, 0, MOD_LAVA); } if (current_player->watertype & CONTENTS_SLIME && !envirosuit) { // no damage from slime with envirosuit T_Damage (current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, 1 * waterlevel, 0, 0, MOD_SLIME); } } }
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 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_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++; }
/* ================= fire_lead This is an internal support routine used for bullet/pellet based weapons. ================= */ static void fire_lead(edict_t * self, vec3_t start, vec3_t aimdir, int damage, int kick, int te_impact, int hspread, int vspread, int mod) { trace_t tr; vec3_t dir; vec3_t forward, right, up; vec3_t end; float r; float u; vec3_t water_start; qboolean water = false; int content_mask = MASK_SHOT | MASK_WATER; tr = gi.trace(self->s.origin, NULL, NULL, start, self, MASK_SHOT); if (!(tr.fraction < 1.0)) { vectoangles(aimdir, dir); AngleVectors(dir, forward, right, up); r = crandom() * hspread; u = crandom() * vspread; VectorMA(start, 8192, forward, end); VectorMA(end, r, right, end); VectorMA(end, u, up, end); if (gi.pointcontents(start) & MASK_WATER) { water = true; VectorCopy(start, water_start); content_mask &= ~MASK_WATER; } tr = gi.trace(start, NULL, NULL, end, self, content_mask); // see if we hit water if (tr.contents & MASK_WATER) { int color; water = true; VectorCopy(tr.endpos, water_start); if (!VectorCompare(start, tr.endpos)) { if (tr.contents & CONTENTS_WATER) { if (strcmp(tr.surface->name, "*brwater") == 0) color = SPLASH_BROWN_WATER; else color = SPLASH_BLUE_WATER; } else if (tr.contents & CONTENTS_SLIME) color = SPLASH_SLIME; else if (tr.contents & CONTENTS_LAVA) color = SPLASH_LAVA; else color = SPLASH_UNKNOWN; if (color != SPLASH_UNKNOWN) { gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_SPLASH); gi.WriteByte(8); gi.WritePosition(tr.endpos); gi.WriteDir(tr.plane.normal); gi.WriteByte(color); gi.multicast(tr.endpos, MULTICAST_PVS); } // change bullet's course when it enters water VectorSubtract(end, start, dir); vectoangles(dir, dir); AngleVectors(dir, forward, right, up); r = crandom() * hspread * 2; u = crandom() * vspread * 2; VectorMA(water_start, 8192, forward, end); VectorMA(end, r, right, end); VectorMA(end, u, up, end); } // re-trace ignoring water this time tr = gi.trace(water_start, NULL, NULL, end, self, MASK_SHOT); } } // send gun puff / flash if (!((tr.surface) && (tr.surface->flags & SURF_SKY))) { if (tr.fraction < 1.0) { if (tr.ent->takedamage) { T_Damage(tr.ent, self, self, aimdir, tr.endpos, tr.plane.normal, damage, kick, DAMAGE_BULLET, mod); } else { if (strncmp(tr.surface->name, "sky", 3) != 0) { gi.WriteByte(svc_temp_entity); gi.WriteByte(te_impact); gi.WritePosition(tr.endpos); gi.WriteDir(tr.plane.normal); gi.multicast(tr.endpos, MULTICAST_PVS); if (self->client) PlayerNoise(self, tr.endpos, PNOISE_IMPACT); } } } } // if went through water, determine where the end and make a bubble trail if (water) { vec3_t pos; VectorSubtract(tr.endpos, water_start, dir); VectorNormalize(dir); VectorMA(tr.endpos, -2, dir, pos); if (gi.pointcontents(pos) & MASK_WATER) VectorCopy(pos, tr.endpos); else tr = gi.trace(pos, NULL, NULL, water_start, tr.ent, MASK_WATER); VectorAdd(water_start, tr.endpos, pos); VectorScale(pos, 0.5, pos); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_BUBBLETRAIL); gi.WritePosition(water_start); gi.WritePosition(tr.endpos); gi.multicast(pos, MULTICAST_PVS); } }
/* * Fires a single blaster bolt. * Used by the blaster and hyper blaster. */ void blaster_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) { int mod; if (!self || !other || !plane || !surf) { G_FreeEdict(self); return; } if (other == self->owner) { return; } if (surf->flags & SURF_SKY) { G_FreeEdict(self); return; } if (self->owner->client) { PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT); } if (other->takedamage) { if (self->spawnflags & 1) { mod = MOD_HYPERBLASTER; } else { mod = MOD_BLASTER; } T_Damage(other, self, self->owner, self->velocity, self->s.origin, plane->normal, self->dmg, 1, DAMAGE_ENERGY, mod); } else { gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_BLASTER); gi.WritePosition(self->s.origin); if (!plane) { gi.WriteDir(vec3_origin); } else { gi.WriteDir(plane->normal); } gi.multicast(self->s.origin, MULTICAST_PVS); } G_FreeEdict(self); }
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 Grenade_Explode(edict_t *ent) { vec3_t origin; int mod; if (!ent) { return; } if (ent->owner && ent->owner->client) { PlayerNoise(ent->owner, ent->s.origin, PNOISE_IMPACT); } if (ent->enemy) { float points; vec3_t v; vec3_t dir; VectorAdd(ent->enemy->mins, ent->enemy->maxs, v); VectorMA(ent->enemy->s.origin, 0.5, v, v); VectorSubtract(ent->s.origin, v, v); points = ent->dmg - 0.5 * VectorLength(v); VectorSubtract(ent->enemy->s.origin, ent->s.origin, dir); if (ent->spawnflags & 1) { mod = MOD_HANDGRENADE; } else { mod = MOD_GRENADE; } T_Damage(ent->enemy, ent, ent->owner, dir, ent->s.origin, vec3_origin, (int)points, (int)points, DAMAGE_RADIUS, mod); } if (ent->spawnflags & 2) { mod = MOD_HELD_GRENADE; } else if (ent->spawnflags & 1) { mod = MOD_HG_SPLASH; } else { mod = MOD_G_SPLASH; } T_RadiusDamage(ent, ent->owner, ent->dmg, ent->enemy, ent->dmg_radius, mod); VectorMA(ent->s.origin, -0.02, ent->velocity, origin); gi.WriteByte(svc_temp_entity); if (ent->waterlevel) { if (ent->groundentity) { gi.WriteByte(TE_GRENADE_EXPLOSION_WATER); } else { gi.WriteByte(TE_ROCKET_EXPLOSION_WATER); } } else { if (ent->groundentity) { gi.WriteByte(TE_GRENADE_EXPLOSION); } else { gi.WriteByte(TE_ROCKET_EXPLOSION); } } gi.WritePosition(origin); gi.multicast(ent->s.origin, MULTICAST_PHS); G_FreeEdict(ent); }
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 rocket_touch(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) { vec3_t origin; int n; if (!ent || !other || !plane || !surf) { G_FreeEdict(ent); return; } if (other == ent->owner) { return; } if (surf->flags & SURF_SKY) { G_FreeEdict(ent); return; } if (ent->owner && ent->owner->client) { PlayerNoise(ent->owner, ent->s.origin, PNOISE_IMPACT); } /* calculate position for the explosion entity */ VectorMA(ent->s.origin, -0.02, ent->velocity, origin); if (other->takedamage) { T_Damage(other, ent, ent->owner, ent->velocity, ent->s.origin, plane->normal, ent->dmg, 0, 0, MOD_ROCKET); } else { /* don't throw any debris in net games */ if (!deathmatch->value && !coop->value) { if ((surf) && !(surf->flags & (SURF_WARP | SURF_TRANS33 | SURF_TRANS66 | SURF_FLOWING))) { n = randk() % 5; while (n--) { ThrowDebris(ent, "models/objects/debris2/tris.md2", 2, ent->s.origin); } } } } T_RadiusDamage(ent, ent->owner, ent->radius_dmg, other, ent->dmg_radius, MOD_R_SPLASH); gi.WriteByte(svc_temp_entity); if (ent->waterlevel) { gi.WriteByte(TE_ROCKET_EXPLOSION_WATER); } else { gi.WriteByte(TE_ROCKET_EXPLOSION); } gi.WritePosition(origin); gi.multicast(ent->s.origin, MULTICAST_PHS); G_FreeEdict(ent); }
/* ============= P_WorldEffects ============= */ void P_WorldEffects (void) { qboolean breather; qboolean envirosuit; int waterlevel, old_waterlevel; if (current_player->movetype == MOVETYPE_NOCLIP) { current_player->air_finished = level.time + 12; // don't need air return; } //K03 Begin //if (HasActiveCurse(current_player, CURSE_FROZEN)) if (que_typeexists(current_player->curses, CURSE_FROZEN)) current_player->air_finished = level.time + 6; //K03 End waterlevel = current_player->waterlevel; old_waterlevel = current_client->old_waterlevel; current_client->old_waterlevel = waterlevel; breather = current_client->breather_framenum > level.framenum; envirosuit = current_client->enviro_framenum > level.framenum; // // if just entered a water volume, play a sound // if (!old_waterlevel && waterlevel) { if ((current_player->client->pers.inventory[ITEM_INDEX(FindItem("Stealth Boots"))] < 1)) { if((current_player->myskills.abilities[CLOAK].disable) || (current_player->myskills.abilities[CLOAK].current_level)) { current_player->lastsound = level.framenum; // trigger monsters PlayerNoise(current_player, current_player->s.origin, PNOISE_SELF); if (current_player->watertype & CONTENTS_LAVA) gi.sound (current_player, CHAN_BODY, gi.soundindex("player/lava_in.wav"), 1, ATTN_NORM, 0); else if (current_player->watertype & CONTENTS_SLIME) gi.sound (current_player, CHAN_BODY, gi.soundindex("player/watr_in.wav"), 1, ATTN_NORM, 0); else if (current_player->watertype & CONTENTS_WATER) gi.sound (current_player, CHAN_BODY, gi.soundindex("player/watr_in.wav"), 1, ATTN_NORM, 0); } } current_player->flags |= FL_INWATER; // clear damage_debounce, so the pain sound will play immediately current_player->damage_debounce_time = level.time - 1; } // // if just completely exited a water volume, play a sound // if (old_waterlevel && ! waterlevel) { if ((current_player->client->pers.inventory[ITEM_INDEX(FindItem("Stealth Boots"))]<1) && !current_player->mtype) { if((current_player->myskills.abilities[CLOAK].disable) || (current_player->myskills.abilities[CLOAK].current_level < 1)) { current_player->lastsound = level.framenum; // trigger monsters PlayerNoise(current_player, current_player->s.origin, PNOISE_SELF); gi.sound (current_player, CHAN_BODY, gi.soundindex("player/watr_out.wav"), 1, ATTN_NORM, 0); } } current_player->flags &= ~FL_INWATER; } // // check for head just going under water // if (old_waterlevel != 3 && waterlevel == 3) { if (current_player->client)//K03 gi.sound (current_player, CHAN_BODY, gi.soundindex("player/watr_un.wav"), 1, ATTN_NORM, 0); } // // check for head just coming out of water // if (old_waterlevel == 3 && waterlevel != 3) { if (current_player->air_finished < level.time) { // gasp for air if (current_player->client)//K03 { gi.sound (current_player, CHAN_VOICE, gi.soundindex("player/gasp1.wav"), 1, ATTN_NORM, 0); PlayerNoise(current_player, current_player->s.origin, PNOISE_SELF); } } else if (current_player->air_finished < level.time + 11) { // just break surface if (current_player->client)//K03 gi.sound (current_player, CHAN_VOICE, gi.soundindex("player/gasp2.wav"), 1, ATTN_NORM, 0); } } // // check for drowning // if (waterlevel == 3) { // breather or envirosuit give air if (breather || envirosuit) { current_player->air_finished = level.time + 10; if (((int)(current_client->breather_framenum - level.framenum) % 25) == 0) { if (current_player->client)//K03 { if (!current_client->breather_sound) gi.sound (current_player, CHAN_AUTO, gi.soundindex("player/u_breath1.wav"), 1, ATTN_NORM, 0); else gi.sound (current_player, CHAN_AUTO, gi.soundindex("player/u_breath2.wav"), 1, ATTN_NORM, 0); current_client->breather_sound ^= 1; PlayerNoise(current_player, current_player->s.origin, PNOISE_SELF); } //FIXME: release a bubble? } } // if out of air, start drowning if ((current_player->air_finished < level.time) && !((current_player->myskills.class_num == CLASS_POLTERGEIST) && (current_player->mtype == 0)) && (current_player->myskills.abilities[WORLD_RESIST].current_level < 1 || HasFlag(current_player)) && !(current_player->flags & FL_GODMODE)) { // drown! if (current_player->client->next_drown_time < level.time && current_player->health > 0) { current_player->client->next_drown_time = level.time + 1; // take more damage the longer underwater current_player->dmg += 2; if (current_player->dmg > 15) current_player->dmg = 15; // play a gurp sound instead of a normal pain sound if (current_player->client) { if (current_player->health <= current_player->dmg) gi.sound (current_player, CHAN_VOICE, gi.soundindex("player/drown1.wav"), 1, ATTN_NORM, 0); else if (rand()&1) gi.sound (current_player, CHAN_VOICE, gi.soundindex("*gurp1.wav"), 1, ATTN_NORM, 0); else gi.sound (current_player, CHAN_VOICE, gi.soundindex("*gurp2.wav"), 1, ATTN_NORM, 0); } current_player->pain_debounce_time = level.time; T_Damage (current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, current_player->dmg, 0, DAMAGE_NO_ARMOR, MOD_WATER); } } } else { current_player->air_finished = level.time + 12; current_player->dmg = 2; } // // check for sizzle damage // if (waterlevel && (current_player->watertype & (CONTENTS_LAVA|CONTENTS_SLIME)) && (current_player->myskills.abilities[WORLD_RESIST].current_level < 1 || HasFlag(current_player)) && !(current_player->flags & FL_GODMODE) && !((current_player->myskills.class_num == CLASS_POLTERGEIST) && (current_player->mtype == 0))) { if (current_player->watertype & CONTENTS_LAVA) { if (current_player->health > 0 && current_player->pain_debounce_time <= level.time && current_client->invincible_framenum < level.framenum) { if (current_player->client)//K03 { if (rand()&1) gi.sound (current_player, CHAN_VOICE, gi.soundindex("player/burn1.wav"), 1, ATTN_NORM, 0); else gi.sound (current_player, CHAN_VOICE, gi.soundindex("player/burn2.wav"), 1, ATTN_NORM, 0); } current_player->pain_debounce_time = level.time + 1; } if (envirosuit) // take 1/3 damage with envirosuit T_Damage (current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, 1*waterlevel, 0, 0, MOD_LAVA); else T_Damage (current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, 3*waterlevel, 0, 0, MOD_LAVA); } if (current_player->watertype & CONTENTS_SLIME) { if (!envirosuit) { // no damage from slime with envirosuit T_Damage (current_player, world, world, vec3_origin, current_player->s.origin, vec3_origin, 1*waterlevel, 0, 0, MOD_SLIME); } } } }
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) { return; } 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) { PF_StartSound(ent, CHAN_VOICE, SV_SoundIndex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ent->pain_debounce_time = level.time + 1; } NoAmmoWeaponChange(ent); return; } 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); PF_WriteByte(svc_muzzleflash); PF_WriteShort(ent - g_edicts); PF_WriteByte(MZ_MACHINEGUN); SV_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; } }