void NPCF_Add( gentity_t *self, gentity_t *ent ) { if ( !ent || !self ) { return; } if ( !ent->client || !self->client ) { return; } if ( self->client->numPlFollowers >= NPCF_MaxFollowers() ) { trap_SendServerCommand( self->client->ps.clientNum, va("print \"No more than %d followers...\n\"", g_NPCmaxFollowers.integer) ); G_EntitySound( self, CHAN_VOICE, G_SoundIndex("*nomore.wav") ); TIMER_Set( ent, "followUse", 1750 ); return; } if ( ent->client->playerTeam == NPCTEAM_NEUTRAL ) { ent->NPC->keepTeam = 1|(ent->client->enemyTeam<<4); ent->client->playerTeam = ent->alliedTeam = ent->s.teamowner = self->client->playerTeam; ent->client->enemyTeam = self->client->enemyTeam; } else { ent->NPC->keepTeam = 0; } self->client->plFollower[self->client->numPlFollowers] = ent; self->client->numPlFollowers++; ent->NPC->defaultBehavior = BS_FOLLOW_LEADER; ent->client->leader = self; ent->client->playerLeader = self; ent->NPC->behaviorState = BS_FOLLOW_LEADER; ent->NPC->defendEnt = self; ent->NPC->eventualGoal = self; NPC_RestoreStats( ent ); //NPC_Respond( ent, self->s.number ); TIMER_Set( ent, "dynamicBehavior", 10000 ); }
void StopGrip(gentity_t*self) { int wasActive = self->client->ps.fd.forcePowersActive; self->client->ps.fd.forceGripUseTime = level.time + 3000; if (self->client->ps.fd.forcePowerLevel[FP_GRIP] > FORCE_LEVEL_1 && g_entities[self->client->ps.fd.forceGripEntityNum].client && g_entities[self->client->ps.fd.forceGripEntityNum].health > 0 && g_entities[self->client->ps.fd.forceGripEntityNum].inuse && (level.time - g_entities[self->client->ps.fd.forceGripEntityNum].client->ps.fd.forceGripStarted) > 500) { //if we had our throat crushed in for more than half a second, gasp for air when we're let go if (wasActive & (1 << FP_GRIP)) { G_EntitySound( &g_entities[self->client->ps.fd.forceGripEntityNum], CHAN_VOICE, G_SoundIndex("*gasp.wav") ); } } if (g_entities[self->client->ps.fd.forceGripEntityNum].client && g_entities[self->client->ps.fd.forceGripEntityNum].inuse) { g_entities[self->client->ps.fd.forceGripEntityNum].client->ps.forceGripChangeMovetype = PM_NORMAL; //[ForceSys] g_entities[self->client->ps.fd.forceGripEntityNum].client->ps.fd.forceGripCripple = 0; //[/ForceSys] g_entities[self->client->ps.fd.forceGripEntityNum].client->forceAttacker = ENTITYNUM_NONE; } if (self->client->ps.forceHandExtend == HANDEXTEND_FORCE_HOLD) { self->client->ps.forceHandExtendTime = 0; } self->client->ps.fd.forceGripEntityNum = ENTITYNUM_NONE; self->client->ps.powerups[PW_DISINT_4] = 0; }
void DoGripAction(gentity_t *self, forcePowers_t forcePower) {//racc - have someone in our grip, deal with them. gentity_t *gripEnt; int gripLevel = 0; trace_t tr; vec3_t a; self->client->dangerTime = level.time; self->client->ps.eFlags &= ~EF_INVULNERABLE; self->client->invulnerableTimer = 0; gripEnt = &g_entities[self->client->ps.fd.forceGripEntityNum]; if (!ValidGripEnt(self,gripEnt)) { WP_ForcePowerStop(self,FP_GRIP); self->client->ps.fd.forceGripEntityNum = ENTITYNUM_NONE; if (gripEnt && gripEnt->client && gripEnt->inuse) { gripEnt->client->ps.forceGripChangeMovetype = PM_NORMAL; } return; } if(gripEnt->client) VectorSubtract(gripEnt->client->ps.origin, self->client->ps.origin, a); else VectorSubtract(gripEnt->s.pos.trBase,self->client->ps.origin,a); if(gripEnt->client) trap_Trace(&tr, self->client->ps.origin, NULL, NULL, gripEnt->client->ps.origin, self->s.number, MASK_PLAYERSOLID); else trap_Trace(&tr, self->client->ps.origin, NULL, NULL, gripEnt->s.pos.trBase, self->s.number, MASK_PLAYERSOLID); //[ForceSys] gripLevel = self->client->ps.fd.forcePowerLevel[FP_GRIP]; if (VectorLength(a) > MAX_GRIP_DISTANCE) { WP_ForcePowerStop(self, forcePower); return; } if(gripEnt->client) { if ( !InFront( gripEnt->client->ps.origin, self->client->ps.origin, self->client->ps.viewangles, 0.9f ) && gripLevel < FORCE_LEVEL_3) { WP_ForcePowerStop(self, forcePower); return; } } else { if ( !InFront( gripEnt->s.pos.trBase, self->client->ps.origin, self->client->ps.viewangles, 0.9f ) && gripLevel < FORCE_LEVEL_3) { WP_ForcePowerStop(self, forcePower); return; } } if (self->client->ps.fd.forcePowerDebounce[FP_GRIP] < level.time) { //2 damage per second while choking, resulting in 10 damage total (not including The Squeeze<tm>) self->client->ps.fd.forcePowerDebounce[FP_GRIP] = level.time + 1000; G_Damage(gripEnt, self, self, NULL, NULL, 2, DAMAGE_NO_ARMOR, MOD_FORCE_DARK); } Jetpack_Off(gripEnt); //make sure the guy being gripped has his jetpack off. if (gripLevel == FORCE_LEVEL_1) { if(gripEnt->client) gripEnt->client->ps.fd.forceGripBeingGripped = level.time + 1000; if(gripEnt->client) if ((level.time - gripEnt->client->ps.fd.forceGripStarted) > 5000) { WP_ForcePowerStop(self, forcePower); return; } } if (gripLevel == FORCE_LEVEL_2||gripLevel==FORCE_LEVEL_3) { gripEnt->client->ps.fd.forceGripBeingGripped = level.time + 1000; if (gripEnt->client->ps.forceGripMoveInterval < level.time) { if(gripLevel == FORCE_LEVEL_2) gripEnt->client->ps.velocity[2] = 15; else gripEnt->client->ps.velocity[2] = 30; gripEnt->client->ps.forceGripMoveInterval = level.time + 300; //only update velocity every 300ms, so as to avoid heavy bandwidth usage } gripEnt->client->ps.otherKiller = self->s.number; gripEnt->client->ps.otherKillerTime = level.time + 5000; gripEnt->client->ps.otherKillerDebounceTime = level.time + 100; //[Asteroids] gripEnt->client->otherKillerMOD = MOD_UNKNOWN; gripEnt->client->otherKillerVehWeapon = 0; gripEnt->client->otherKillerWeaponType = WP_NONE; //[/Asteroids] gripEnt->client->ps.forceGripChangeMovetype = PM_FLOAT; if(gripEnt->client) { if ((level.time - gripEnt->client->ps.fd.forceGripStarted) > 3000 && !self->client->ps.fd.forceGripDamageDebounceTime) { //if we managed to lift him into the air for 2 seconds, give him a crack self->client->ps.fd.forceGripDamageDebounceTime = 1; if(gripLevel == FORCE_LEVEL_2) G_Damage(gripEnt, self, self, NULL, NULL, 20, DAMAGE_NO_ARMOR, MOD_FORCE_DARK); else G_Damage(gripEnt, self, self, NULL, NULL, 75, DAMAGE_NO_ARMOR, MOD_FORCE_DARK); //Must play custom sounds on the actual entity. Don't use G_Sound (it creates a temp entity for the sound) G_EntitySound( gripEnt, CHAN_VOICE, G_SoundIndex(va( "*choke%d.wav", Q_irand( 1, 3 ) )) ); gripEnt->client->ps.forceHandExtend = HANDEXTEND_CHOKE; gripEnt->client->ps.forceHandExtendTime = level.time + 2000; if (gripEnt->client->ps.fd.forcePowersActive & (1 << FP_GRIP)) { //choking, so don't let him keep gripping himself WP_ForcePowerStop(gripEnt, FP_GRIP); return; } } else if ((level.time - gripEnt->client->ps.fd.forceGripStarted) > 4000) { WP_ForcePowerStop(self, forcePower); return; } } } }
void hurt_touch( gentity_t *self, gentity_t *other, trace_t *trace ) { int dflags; if ( self->flags & FL_INACTIVE ) {//set by target_deactivate return; } if ( !other->takedamage ) { return; } if ( self->timestamp > level.time ) { return; } if (self->damage == -1 && other && other->client && other->health < 1) { other->client->ps.fallingToDeath = 0; respawn(other); return; } if (self->damage == -1 && other && other->client && other->client->ps.fallingToDeath) { return; } if ( self->spawnflags & 16 ) { self->timestamp = level.time + 1000; } else { self->timestamp = level.time + FRAMETIME; } // play sound /* if ( !(self->spawnflags & 4) && self->damage != -1 ) { G_Sound( other, CHAN_AUTO, self->noise_index ); } */ if (self->spawnflags & 8) dflags = DAMAGE_NO_PROTECTION; else dflags = 0; if (self->damage == -1 && other && other->client) { if (other->client->ps.otherKillerTime > level.time) { //we're as good as dead, so if someone pushed us into this then remember them other->client->ps.otherKillerTime = level.time + 20000; other->client->ps.otherKillerDebounceTime = level.time + 10000; } other->client->ps.fallingToDeath = level.time; //rag on the way down, this flag will automatically be cleared for us on respawn other->client->ps.eFlags |= EF_RAG; //make sure his jetpack is off Jetpack_Off(other); if (other->NPC) { //kill it now vec3_t vDir; VectorSet(vDir, 0, 1, 0); G_Damage(other, other, other, vDir, other->client->ps.origin, Q3_INFINITE, 0, MOD_FALLING); } else { G_EntitySound(other, CHAN_VOICE, G_SoundIndex("*falling1.wav")); } self->timestamp = 0; //do not ignore others } else { int dmg = self->damage; if (dmg == -1) { //so fall-to-blackness triggers destroy evertyhing dmg = 99999; self->timestamp = 0; } if (self->activator && self->activator->inuse && self->activator->client) { G_Damage (other, self->activator, self->activator, NULL, NULL, dmg, dflags|DAMAGE_NO_PROTECTION, MOD_TRIGGER_HURT); } else { G_Damage (other, self, self, NULL, NULL, dmg, dflags|DAMAGE_NO_PROTECTION, MOD_TRIGGER_HURT); } } }
void hurt_touch( gentity_t *self, gentity_t *other, trace_t *trace ) { int dflags; if ( !other->takedamage ) { return; } if ( self->timestamp > level.time ) { return; } if (self->damage == -1 && other && other->client && other->health < 1) { other->client->ps.fallingToDeath = 0; respawn(other); return; } if (self->damage == -1 && other && other->client && other->client->ps.fallingToDeath) { return; } if ( self->spawnflags & 16 ) { self->timestamp = level.time + 1000; } else { self->timestamp = level.time + FRAMETIME; } // play sound if ( !(self->spawnflags & 4) && self->damage != -1 ) { G_Sound( other, CHAN_AUTO, self->noise_index ); } if (self->spawnflags & 8) dflags = DAMAGE_NO_PROTECTION; else dflags = 0; if (self->damage == -1 && other && other->client) { if (other->client->ps.otherKillerTime > level.time) { //we're as good as dead, so if someone pushed us into this then remember them other->client->ps.otherKillerTime = level.time + 20000; other->client->ps.otherKillerDebounceTime = level.time + 10000; } other->client->ps.fallingToDeath = level.time; self->timestamp = 0; //do not ignore others G_EntitySound(other, CHAN_VOICE, G_SoundIndex("*falling1.wav")); } else { int dmg = self->damage; if (dmg == -1) { //so fall-to-blackness triggers destroy evertyhing dmg = 99999; self->timestamp = 0; } if (self->activator && self->activator->inuse && self->activator->client) { G_Damage (other, self->activator, self->activator, NULL, NULL, dmg, dflags|DAMAGE_NO_PROTECTION, MOD_TRIGGER_HURT); } else { G_Damage (other, self, self, NULL, NULL, dmg, dflags|DAMAGE_NO_PROTECTION, MOD_TRIGGER_HURT); } } }
void JKG_GrappleUpdate( gentity_t *self ) { gentity_t *grappler = &g_entities[self->client->grappleIndex]; if (!grappler->inuse || !grappler->client || grappler->client->grappleIndex != self->s.number || !BG_InGrappleMove(grappler->client->ps.torsoAnim) || !BG_InGrappleMove(grappler->client->ps.legsAnim) || !BG_InGrappleMove(self->client->ps.torsoAnim) || !BG_InGrappleMove(self->client->ps.legsAnim) || !self->client->grappleState || !grappler->client->grappleState || grappler->health < 1 || self->health < 1 || !G_PrettyCloseIGuess(self->client->ps.origin[2], grappler->client->ps.origin[2], 4.0f)) { self->client->grappleState = 0; if ((BG_InGrappleMove(self->client->ps.torsoAnim) && self->client->ps.torsoTimer > 100) || (BG_InGrappleMove(self->client->ps.legsAnim) && self->client->ps.legsTimer > 100)) { //if they're pretty far from finishing the anim then shove them into another anim G_SetAnim(self, &self->client->pers.cmd, SETANIM_BOTH, BOTH_KYLE_MISS, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0); if (self->client->ps.torsoAnim == BOTH_KYLE_MISS) { //providing the anim set succeeded.. self->client->ps.weaponTime = self->client->ps.torsoTimer; } } } else { vec3_t grapAng; VectorSubtract(grappler->client->ps.origin, self->client->ps.origin, grapAng); if (VectorLength(grapAng) > 64.0f) { //too far away, break it off if ((BG_InGrappleMove(self->client->ps.torsoAnim) && self->client->ps.torsoTimer > 100) || (BG_InGrappleMove(self->client->ps.legsAnim) && self->client->ps.legsTimer > 100)) { self->client->grappleState = 0; G_SetAnim(self, &self->client->pers.cmd, SETANIM_BOTH, BOTH_KYLE_MISS, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0); if (self->client->ps.torsoAnim == BOTH_KYLE_MISS) { //providing the anim set succeeded.. self->client->ps.weaponTime = self->client->ps.torsoTimer; } } } else { vectoangles(grapAng, grapAng); SetClientViewAngle(self, grapAng); if (self->client->grappleState >= 20) { //grapplee //try to position myself at the correct distance from my grappler float idealDist; vec3_t gFwd, idealSpot; trace_t trace; if (grappler->client->ps.torsoAnim == BOTH_KYLE_PA_1) { //grab punch idealDist = 46.0f; } else { //knee-throw idealDist = 34.0f; } AngleVectors(grappler->client->ps.viewangles, gFwd, 0, 0); VectorMA(grappler->client->ps.origin, idealDist, gFwd, idealSpot); trap_Trace(&trace, self->client->ps.origin, self->r.mins, self->r.maxs, idealSpot, self->s.number, self->clipmask); if (!trace.startsolid && !trace.allsolid && trace.fraction == 1.0f) { //go there G_SetOrigin(self, idealSpot); VectorCopy(idealSpot, self->client->ps.origin); } } else if (self->client->grappleState >= 1) { //grappler if (grappler->client->ps.weapon == WP_SABER) { //make sure their saber is shut off if (!grappler->client->ps.saberHolstered) { grappler->client->ps.saberHolstered = 2; if (grappler->client->saber[0].soundOff) { G_Sound(grappler, CHAN_AUTO, grappler->client->saber[0].soundOff); } if (grappler->client->saber[1].soundOff && grappler->client->saber[1].model[0]) { G_Sound(grappler, CHAN_AUTO, grappler->client->saber[1].soundOff); } } } //check for smashy events if (self->client->ps.torsoAnim == BOTH_KYLE_PA_1) { //grab punch if (self->client->grappleState == 1) { //smack if (self->client->ps.torsoTimer < 3400) { int grapplerAnim = grappler->client->ps.torsoAnim; int grapplerTime = grappler->client->ps.torsoTimer; G_Damage(grappler, self, self, NULL, self->client->ps.origin, 10, 0, MOD_MELEE); //G_Sound( grappler, CHAN_AUTO, G_SoundIndex( va( "sound/weapons/melee/punch%d", Q_irand( 1, 4 ) ) ) ); //it might try to put them into a pain anim or something, so override it back again if (grappler->health > 0) { grappler->client->ps.torsoAnim = grapplerAnim; grappler->client->ps.torsoTimer = grapplerTime; grappler->client->ps.legsAnim = grapplerAnim; grappler->client->ps.legsTimer = grapplerTime; grappler->client->ps.weaponTime = grapplerTime; } self->client->grappleState++; } } else if (self->client->grappleState == 2) { //smack! if (self->client->ps.torsoTimer < 2550) { int grapplerAnim = grappler->client->ps.torsoAnim; int grapplerTime = grappler->client->ps.torsoTimer; G_Damage(grappler, self, self, NULL, self->client->ps.origin, 10, 0, MOD_MELEE); //G_Sound( grappler, CHAN_AUTO, G_SoundIndex( va( "sound/weapons/melee/punch%d", Q_irand( 1, 4 ) ) ) ); //it might try to put them into a pain anim or something, so override it back again if (grappler->health > 0) { grappler->client->ps.torsoAnim = grapplerAnim; grappler->client->ps.torsoTimer = grapplerTime; grappler->client->ps.legsAnim = grapplerAnim; grappler->client->ps.legsTimer = grapplerTime; grappler->client->ps.weaponTime = grapplerTime; } self->client->grappleState++; } } else { //SMACK! if (self->client->ps.torsoTimer < 1300) { vec3_t tossDir; G_Damage(grappler, self, self, NULL, self->client->ps.origin, 30, 0, MOD_MELEE); //G_Sound( grappler, CHAN_AUTO, G_SoundIndex( va( "sound/weapons/melee/punch%d", Q_irand( 1, 4 ) ) ) ); self->client->grappleState = 0; VectorSubtract(grappler->client->ps.origin, self->client->ps.origin, tossDir); VectorNormalize(tossDir); VectorScale(tossDir, 500.0f, tossDir); tossDir[2] = 200.0f; VectorAdd(grappler->client->ps.velocity, tossDir, grappler->client->ps.velocity); if (grappler->health > 0) { //if still alive knock them down grappler->client->ps.forceHandExtend = HANDEXTEND_KNOCKDOWN; grappler->client->ps.forceHandExtendTime = level.time + 1300; } } } } else if (self->client->ps.torsoAnim == BOTH_KYLE_PA_2) { //knee throw if (self->client->grappleState == 1) { //knee to the face if (self->client->ps.torsoTimer < 3200) { int grapplerAnim = grappler->client->ps.torsoAnim; int grapplerTime = grappler->client->ps.torsoTimer; G_Damage(grappler, self, self, NULL, self->client->ps.origin, 20, 0, MOD_MELEE); //G_Sound( grappler, CHAN_AUTO, G_SoundIndex( va( "sound/weapons/melee/punch%d", Q_irand( 1, 4 ) ) ) ); //it might try to put them into a pain anim or something, so override it back again if (grappler->health > 0) { grappler->client->ps.torsoAnim = grapplerAnim; grappler->client->ps.torsoTimer = grapplerTime; grappler->client->ps.legsAnim = grapplerAnim; grappler->client->ps.legsTimer = grapplerTime; grappler->client->ps.weaponTime = grapplerTime; } self->client->grappleState++; } } else if (self->client->grappleState == 2) { //smashed on the ground if (self->client->ps.torsoTimer < 2000) { //G_Damage(grappler, self, self, NULL, self->client->ps.origin, 10, 0, MOD_MELEE); //don't do damage on this one, it would look very freaky if they died G_EntitySound( grappler, CHAN_VOICE, G_SoundIndex("*pain100.wav") ); //G_Sound( grappler, CHAN_AUTO, G_SoundIndex( va( "sound/weapons/melee/punch%d", Q_irand( 1, 4 ) ) ) ); self->client->grappleState++; } } else { //and another smash if (self->client->ps.torsoTimer < 1000) { G_Damage(grappler, self, self, NULL, self->client->ps.origin, 30, 0, MOD_MELEE); //G_Sound( grappler, CHAN_AUTO, G_SoundIndex( va( "sound/weapons/melee/punch%d", Q_irand( 1, 4 ) ) ) ); //it might try to put them into a pain anim or something, so override it back again if (grappler->health > 0) { grappler->client->ps.torsoTimer = 1000; //G_SetAnim(grappler, &grappler->client->pers.cmd, SETANIM_BOTH, BOTH_GETUP3, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0); grappler->client->grappleState = 0; } else { //override death anim grappler->client->ps.torsoAnim = BOTH_DEADFLOP1; grappler->client->ps.legsAnim = BOTH_DEADFLOP1; } self->client->grappleState = 0; } } } else { //? } } } } }