/* ============== Team_DroppedFlagThink Automatically set in Launch_Item if the item is one of the flags Flags are unique in that if they are dropped, the base flag must be respawned when they time out ============== */ void Team_DroppedFlagThink(gentity_t *ent) { if (ent->item->giTag == PW_REDFLAG) { G_Script_ScriptEvent(&g_entities[ent->s.otherEntityNum], "trigger", "returned"); Team_ReturnFlagSound(ent, TEAM_AXIS); Team_ResetFlag(ent); if (level.gameManager) { G_Script_ScriptEvent(level.gameManager, "trigger", "axis_object_returned"); } // Nico, bugfix: removed left printf // http://games.chruker.dk/enemy_territory/modding_project_bugfix.php?bug_id=058 // trap_SendServerCommand( -1, "cp \"Axis have returned the objective!\" 2" ); } else if (ent->item->giTag == PW_BLUEFLAG) { G_Script_ScriptEvent(&g_entities[ent->s.otherEntityNum], "trigger", "returned"); Team_ReturnFlagSound(ent, TEAM_ALLIES); Team_ResetFlag(ent); if (level.gameManager) { G_Script_ScriptEvent(level.gameManager, "trigger", "allied_object_returned"); } } // Reset Flag will delete this entity }
/** * @brief Automatically set in Launch_Item if the item is one of the flags * * @details Flags are unique in that if they are dropped, the base flag must be respawned when they time out * * @param[in] ent */ void Team_DroppedFlagThink(gentity_t *ent) { if (ent->item->giTag == PW_REDFLAG) { G_Script_ScriptEvent(&g_entities[ent->s.otherEntityNum], "trigger", "returned"); Team_ReturnFlagSound(ent, TEAM_AXIS); Team_ResetFlag(ent); if (level.gameManager) { G_Script_ScriptEvent(level.gameManager, "trigger", "axis_object_returned"); } } else if (ent->item->giTag == PW_BLUEFLAG) { G_Script_ScriptEvent(&g_entities[ent->s.otherEntityNum], "trigger", "returned"); Team_ReturnFlagSound(ent, TEAM_ALLIES); Team_ResetFlag(ent); if (level.gameManager) { G_Script_ScriptEvent(level.gameManager, "trigger", "allied_object_returned"); } } // Reset Flag will delete this entity }
/* =============== G_CallSpawn Finds the spawn function for the entity and calls it, returning qfalse if not found =============== */ qboolean G_CallSpawn(gentity_t *ent) { spawn_t *s; gitem_t *item; if (!ent->classname) { G_Printf("G_CallSpawn: NULL classname\n"); return qfalse; } // check item spawn functions for (item = bg_itemlist + 1 ; item->classname ; item++) { if (!strcmp(item->classname, ent->classname)) { // found it if (g_gametype.integer != GT_WOLF_LMS) // lets not have items in last man standing for the moment { G_SpawnItem(ent, item); G_Script_ScriptParse(ent); G_Script_ScriptEvent(ent, "spawn", ""); } else { return qfalse; } return qtrue; } } // check normal spawn functions for (s = spawns ; s->name ; s++) { if (!strcmp(s->name, ent->classname)) { // found it s->spawn(ent); // entity scripting if (/*ent->s.number >= MAX_CLIENTS &&*/ ent->scriptName) { G_Script_ScriptParse(ent); G_Script_ScriptEvent(ent, "spawn", ""); } return qtrue; } } // hack: this avoids spammy prints on start, bsp uses obsolete classnames! // bot_sniper_spot (railgun) if (Q_stricmp(ent->classname, "bot_sniper_spot")) { G_Printf("%s doesn't have a spawn function\n", ent->classname); } return qfalse; }
/*QUAKED target_script_trigger (1 .7 .2) (-8 -8 -8) (8 8 8) must have an aiName must have a target when used it will fire its targets */ void target_script_trigger_use(gentity_t *ent, gentity_t *other, gentity_t *activator) { // START Mad Doctor I changes, 8/16/2002 qboolean found = qfalse; // Nico, silent GCC (void)activator; // Are we using ainame to find another ent instead of using scriptname for this one? if (ent->aiName) { gentity_t *trent = NULL; // Find the first entity with this name trent = G_Find(trent, FOFS(scriptName), ent->aiName); // Was there one? if (trent) { // We found it found = qtrue; // Play the script G_Script_ScriptEvent(trent, "trigger", ent->target); } // if (trent)... } // if (ent->aiName)... // Use the old method if we didn't find an entity with the ainame if (!found && ent->scriptName) { G_Script_ScriptEvent(ent, "trigger", ent->target); } G_UseTargets(ent, other); }
void Touch_flagonly( gentity_t *ent, gentity_t *other, trace_t *trace ) { if ( !other->client ) { return; } if ( ent->spawnflags & RED_FLAG && other->client->ps.powerups[ PW_REDFLAG ] ) { AddScore( other, ent->accuracy ); // JPW NERVE set from map, defaults to 20 G_Script_ScriptEvent( ent, "death", "" ); // Removes itself ent->touch = 0; ent->nextthink = level.time + FRAMETIME; ent->think = G_FreeEntity; } else if ( ent->spawnflags & BLUE_FLAG && other->client->ps.powerups[ PW_BLUEFLAG ] ) { AddScore( other, ent->accuracy ); // JPW NERVE set from map, defaults to 20 G_Script_ScriptEvent( ent, "death", "" ); // Removes itself ent->touch = 0; ent->nextthink = level.time + FRAMETIME; ent->think = G_FreeEntity; } }
int Team_TouchOurFlag(gentity_t *ent, gentity_t *other, int team) { gclient_t *cl = other->client; if (ent->flags & FL_DROPPED_ITEM) { // hey, its not home. return it by teleporting it back if (cl->sess.sessionTeam == TEAM_AXIS) { if (level.gameManager) { G_Script_ScriptEvent(level.gameManager, "trigger", "axis_object_returned"); } G_Script_ScriptEvent(&g_entities[ent->s.otherEntityNum], "trigger", "returned"); } else { if (level.gameManager) { G_Script_ScriptEvent(level.gameManager, "trigger", "allied_object_returned"); } G_Script_ScriptEvent(&g_entities[ent->s.otherEntityNum], "trigger", "returned"); } // dhm // jpw 800 672 2420 //ResetFlag will remove this entity! We must return zero Team_ReturnFlagSound(ent, team); Team_ResetFlag(ent); return 0; } // DHM - Nerve :: GT_WOLF doesn't support capturing the flag return 0; }
void Touch_flagonly (gentity_t *ent, gentity_t *other, trace_t *trace) { gentity_t* tmp; if (!other->client) return; if ( ent->spawnflags & RED_FLAG && other->client->ps.powerups[ PW_REDFLAG ] ) { if( ent->spawnflags & 4 ) { other->client->ps.powerups[ PW_REDFLAG ] = 0; other->client->speedScale = 0; } AddScore(other, ent->accuracy); // JPW NERVE set from map, defaults to 20 //G_AddExperience( other, 2.f ); tmp = ent->parent; ent->parent = other; G_Script_ScriptEvent( ent, "death", "" ); G_Script_ScriptEvent( &g_entities[other->client->flagParent], "trigger", "captured" ); ent->parent = tmp; // Removes itself ent->touch = NULL; ent->nextthink = level.time + FRAMETIME; ent->think = G_FreeEntity; } else if ( ent->spawnflags & BLUE_FLAG && other->client->ps.powerups[ PW_BLUEFLAG ] ) { if( ent->spawnflags & 4 ) { other->client->ps.powerups[ PW_BLUEFLAG ] = 0; other->client->speedScale = 0; } AddScore(other, ent->accuracy); // JPW NERVE set from map, defaults to 20 //G_AddExperience( other, 2.f ); tmp = ent->parent; ent->parent = other; G_Script_ScriptEvent( ent, "death", "" ); G_Script_ScriptEvent( &g_entities[other->client->flagParent], "trigger", "captured" ); ent->parent = tmp; // Removes itself ent->touch = NULL; ent->nextthink = level.time + FRAMETIME; ent->think = G_FreeEntity; } }
/* =============== G_CallSpawn Finds the spawn function for the entity and calls it, returning qfalse if not found =============== */ qboolean G_CallSpawn(gentity_t * ent) { spawn_t *s; gitem_t *item; if(!ent->classname) { G_Printf("G_CallSpawn: NULL classname\n"); return qfalse; } // check item spawn functions for(item = bg_itemlist + 1; item->classname; item++) { if(!strcmp(item->classname, ent->classname)) { // found it if(g_gametype.integer != GT_WOLF_LMS) { // Gordon: lets not have items in last man standing for the moment G_SpawnItem(ent, item); G_Script_ScriptParse(ent); G_Script_ScriptEvent(ent, "spawn", ""); } else { return qfalse; } return qtrue; } } // check normal spawn functions for(s = spawns; s->name; s++) { if(!strcmp(s->name, ent->classname)) { // found it s->spawn(ent); // RF, entity scripting if( /*ent->s.number >= MAX_CLIENTS && */ ent->scriptName) { G_Script_ScriptParse(ent); G_Script_ScriptEvent(ent, "spawn", ""); } return qtrue; } } G_Printf("%s doesn't have a spawn function\n", ent->classname); return qfalse; }
int Team_TouchEnemyFlag(gentity_t *ent, gentity_t *other, int team) { gclient_t *cl = other->client; gentity_t *tmp; ent->s.density--; tmp = ent->parent; ent->parent = other; if (cl->sess.sessionTeam == TEAM_AXIS) { gentity_t *pm = G_PopupMessage(PM_OBJECTIVE); pm->s.effect3Time = G_StringIndex(ent->message); pm->s.effect2Time = TEAM_AXIS; pm->s.density = 0; // 0 = stolen if (level.gameManager) { G_Script_ScriptEvent(level.gameManager, "trigger", "allied_object_stolen"); } G_Script_ScriptEvent(ent, "trigger", "stolen"); } else { gentity_t *pm = G_PopupMessage(PM_OBJECTIVE); pm->s.effect3Time = G_StringIndex(ent->message); pm->s.effect2Time = TEAM_ALLIES; pm->s.density = 0; // 0 = stolen if (level.gameManager) { G_Script_ScriptEvent(level.gameManager, "trigger", "axis_object_stolen"); } G_Script_ScriptEvent(ent, "trigger", "stolen"); } ent->parent = tmp; if (team == TEAM_AXIS) { cl->ps.powerups[PW_REDFLAG] = INT_MAX; } else { cl->ps.powerups[PW_BLUEFLAG] = INT_MAX; } // flags never expire // store the entitynum of our original flag spawner if (ent->flags & FL_DROPPED_ITEM) { cl->flagParent = ent->s.otherEntityNum; } else { cl->flagParent = ent->s.number; } other->client->speedScale = ent->splashDamage; // Alter player speed if (ent->s.density > 0) { return 1; // We have more flags to give out, spawn back quickly } return -1; // Do not respawn this automatically, but do delete it if it was FL_DROPPED }
void Touch_flagonly(gentity_t *ent, gentity_t *other, trace_t *trace) { gentity_t *tmp; // Nico, silent GCC (void)trace; if (!other->client) { return; } if (ent->spawnflags & RED_FLAG && other->client->ps.powerups[PW_REDFLAG]) { if (ent->spawnflags & 4) { other->client->ps.powerups[PW_REDFLAG] = 0; other->client->speedScale = 0; } tmp = ent->parent; ent->parent = other; G_Script_ScriptEvent(ent, "death", ""); G_Script_ScriptEvent(&g_entities[other->client->flagParent], "trigger", "captured"); ent->parent = tmp; // Removes itself ent->touch = NULL; ent->nextthink = level.time + FRAMETIME; ent->think = G_FreeEntity; } else if (ent->spawnflags & BLUE_FLAG && other->client->ps.powerups[PW_BLUEFLAG]) { if (ent->spawnflags & 4) { other->client->ps.powerups[PW_BLUEFLAG] = 0; other->client->speedScale = 0; } tmp = ent->parent; ent->parent = other; G_Script_ScriptEvent(ent, "death", ""); G_Script_ScriptEvent(&g_entities[other->client->flagParent], "trigger", "captured"); ent->parent = tmp; // Removes itself ent->touch = NULL; ent->nextthink = level.time + FRAMETIME; ent->think = G_FreeEntity; } }
void Touch_flagonly_multiple(gentity_t * ent, gentity_t * other, trace_t * trace) { gentity_t *tmp; if(!other->client) { return; } if(ent->spawnflags & RED_FLAG && other->client->ps.powerups[PW_REDFLAG]) { other->client->ps.powerups[PW_REDFLAG] = 0; other->client->speedScale = 0; AddScore(other, ent->accuracy); // JPW NERVE set from map, defaults to 20 //G_AddExperience( other, 2.f ); tmp = ent->parent; ent->parent = other; G_Script_ScriptEvent(ent, "death", ""); G_Script_ScriptEvent(&g_entities[other->client->flagParent], "trigger", "captured"); #ifdef OMNIBOT Bot_Util_SendTrigger(ent, NULL, va("Allies captured %s", ent->scriptName), ""); #endif ent->parent = tmp; } else if(ent->spawnflags & BLUE_FLAG && other->client->ps.powerups[PW_BLUEFLAG]) { other->client->ps.powerups[PW_BLUEFLAG] = 0; other->client->speedScale = 0; AddScore(other, ent->accuracy); // JPW NERVE set from map, defaults to 20 //G_AddExperience( other, 2.f ); tmp = ent->parent; ent->parent = other; G_Script_ScriptEvent(ent, "death", ""); G_Script_ScriptEvent(&g_entities[other->client->flagParent], "trigger", "captured"); #ifdef OMNIBOT Bot_Util_SendTrigger(ent, NULL, va("Axis captured %s", ent->scriptName), ""); #endif ent->parent = tmp; } }
void checkpoint_touch(gentity_t *self, gentity_t *other, trace_t *trace) { // Nico, silent GCC (void)trace; if (self->count == (int)other->client->sess.sessionTeam) { return; } // Set controlling team self->count = other->client->sess.sessionTeam; // Set animation if (self->count == TEAM_AXIS) { if (self->s.frame == WCP_ANIM_NOFLAG) { self->s.frame = WCP_ANIM_RAISE_AXIS; } else if (self->s.frame == WCP_ANIM_AMERICAN_RAISED) { self->s.frame = WCP_ANIM_AMERICAN_TO_AXIS; } else { self->s.frame = WCP_ANIM_AXIS_RAISED; } } else { if (self->s.frame == WCP_ANIM_NOFLAG) { self->s.frame = WCP_ANIM_RAISE_AMERICAN; } else if (self->s.frame == WCP_ANIM_AXIS_RAISED) { self->s.frame = WCP_ANIM_AXIS_TO_AMERICAN; } else { self->s.frame = WCP_ANIM_AMERICAN_RAISED; } } self->parent = other; // Gordon: reset player disguise on touching flag // Run script trigger if (self->count == TEAM_AXIS) { self->health = 0; G_Script_ScriptEvent(self, "trigger", "axis_capture"); } else { self->health = 10; G_Script_ScriptEvent(self, "trigger", "allied_capture"); } // Play a sound G_AddEvent(self, EV_GENERAL_SOUND, self->soundPos1); // Don't allow touch again until animation is finished self->touch = NULL; self->think = checkpoint_think; self->nextthink = level.time + 1000; }
// the trigger was just activated // ent->activator should be set to the activator so it can be held through a delay // so wait for the delay time before firing void multi_trigger(gentity_t * ent, gentity_t * activator) { ent->activator = activator; G_Script_ScriptEvent(ent, "activate", NULL); if(ent->nextthink) { return; // can't retrigger until the wait is over } G_UseTargets(ent, ent->activator); if(ent->wait > 0) { ent->think = multi_wait; ent->nextthink = level.time + (ent->wait + ent->random * crandom()) * 1000; } else { // we can't just remove (self) here, because this is a touch function // called while looping through area links... ent->touch = 0; ent->nextthink = level.time + FRAMETIME; ent->think = G_FreeEntity; } }
/** * @brief Team_TouchOurFlag * @param[in] ent * @param[in] other * @param[in] team * @return */ int Team_TouchOurFlag(gentity_t *ent, gentity_t *other, int team) { gclient_t *cl = other->client; if (ent->flags & FL_DROPPED_ITEM) { // hey, its not home. return it by teleporting it back AddScore(other, WOLF_SECURE_OBJ_BONUS); if (cl->sess.sessionTeam == TEAM_AXIS) { if (level.gameManager) { G_Script_ScriptEvent(level.gameManager, "trigger", "axis_object_returned"); } G_Script_ScriptEvent(&g_entities[ent->s.otherEntityNum], "trigger", "returned"); #ifdef FEATURE_OMNIBOT { const char *pName = ent->message ? ent->message : _GetEntityName(ent); Bot_Util_SendTrigger(ent, NULL, va("Axis have returned %s!", pName ? pName : ""), "returned"); } #endif } else { if (level.gameManager) { G_Script_ScriptEvent(level.gameManager, "trigger", "allied_object_returned"); } G_Script_ScriptEvent(&g_entities[ent->s.otherEntityNum], "trigger", "returned"); #ifdef FEATURE_OMNIBOT { const char *pName = ent->message ? ent->message : _GetEntityName(ent); Bot_Util_SendTrigger(ent, NULL, va("Allies have returned %s!", pName ? pName : ""), "returned"); } #endif } //ResetFlag will remove this entity! We must return zero Team_ReturnFlagSound(ent, team); Team_ResetFlag(ent); return 0; } // GT_WOLF doesn't support capturing the flag return 0; }
/* =============== G_CallSpawn Finds the spawn function for the entity and calls it, returning qfalse if not found =============== */ qboolean G_CallSpawn( gentity_t *ent ) { spawn_t *s; gitem_t *item; int hash; if ( !ent->classname ) { G_Printf( "G_CallSpawn: NULL classname\n" ); return qfalse; } if ( g_deathmatch.integer ) { if ( !strcmp( "func_explosive", ent->classname ) ) { return qfalse; } if ( !strcmp( "trigger_hurt", ent->classname ) ) { return qfalse; } // don't spawn the flags in cp if ( g_gametype.integer == 7 && !strcmp( "team_WOLF_checkpoint", ent->classname ) ) { return qfalse; } } // check item spawn functions for ( item = bg_itemlist + 1 ; item->classname ; item++ ) { if ( !strcmp( item->classname, ent->classname ) ) { // found it // DHM - Nerve :: allow flags in GTWOLF if ( item->giType == IT_TEAM && ( g_gametype.integer != GT_CTF && g_gametype.integer < GT_WOLF ) ) { return qfalse; } G_SpawnItem( ent, item ); return qtrue; } } // check normal spawn functions hash = BG_StringHashValue( ent->classname ); for ( s = spawns ; s->name ; s++ ) { if ( s->hash == hash ) { // found it s->spawn( ent ); // RF, entity scripting if ( ent->s.number >= MAX_CLIENTS && ent->scriptName ) { G_Script_ScriptParse( ent ); G_Script_ScriptEvent( ent, "spawn", "" ); } return qtrue; } } G_Printf( "%s doesn't have a spawn function\n", ent->classname ); return qfalse; }
void checkpoint_touch( gentity_t *self, gentity_t *other, trace_t *trace ) { if ( self->count == other->client->sess.sessionTeam ) { return; } // Set controlling team self->count = other->client->sess.sessionTeam; // Set animation if ( self->count == TEAM_RED ) { if ( self->s.frame == WCP_ANIM_NOFLAG ) { self->s.frame = WCP_ANIM_RAISE_NAZI; } else if ( self->s.frame == WCP_ANIM_AMERICAN_RAISED ) { self->s.frame = WCP_ANIM_AMERICAN_TO_NAZI; } else { self->s.frame = WCP_ANIM_NAZI_RAISED; } } else { if ( self->s.frame == WCP_ANIM_NOFLAG ) { self->s.frame = WCP_ANIM_RAISE_AMERICAN; } else if ( self->s.frame == WCP_ANIM_NAZI_RAISED ) { self->s.frame = WCP_ANIM_NAZI_TO_AMERICAN; } else { self->s.frame = WCP_ANIM_AMERICAN_RAISED; } } // Run script trigger if ( self->count == TEAM_RED ) { G_Script_ScriptEvent( self, "trigger", "axis_capture" ); } else { G_Script_ScriptEvent( self, "trigger", "allied_capture" ); } // Play a sound G_AddEvent( self, EV_GENERAL_SOUND, self->soundPos1 ); // Don't allow touch again until animation is finished self->touch = NULL; self->think = checkpoint_think; self->nextthink = level.time + 1000; }
// the trigger was just activated // ent->activator should be set to the activator so it can be held through a delay // so wait for the delay time before firing void multi_trigger(gentity_t *ent, gentity_t *activator) { ent->activator = activator; if (ent->numPlayers > 1) { gentity_t *tnt; // temp ent for counting players int i; int entList[MAX_GENTITIES]; // list of entities int cnt = trap_EntitiesInBox(ent->r.mins, ent->r.maxs, entList, MAX_GENTITIES); int players = 0; // number of ents in trigger for (i = 0; i < cnt; i++) { tnt = &g_entities[entList[i]]; if (tnt->client) { players++; } } // not enough players, return if (players < ent->numPlayers) { return; } } G_Script_ScriptEvent(ent, "activate", NULL); if (ent->nextthink) { return; // can't retrigger until the wait is over } G_UseTargets(ent, ent->activator); if (ent->wait > 0) { ent->think = multi_wait; ent->nextthink = level.time + (ent->wait + ent->random * crandom()) * 1000; } else { // we can't just remove (self) here, because this is a touch function // called while looping through area links... ent->touch = 0; ent->nextthink = level.time + FRAMETIME; ent->think = G_FreeEntity; } }
void script_mover_die(gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int mod) { G_Script_ScriptEvent( self, "death", "" ); if (!(self->spawnflags & 8)) { G_FreeEntity( self ); } if( self->tankLink ) { G_LeaveTank( self->tankLink, qtrue ); } self->die = NULL; }
/* =============== G_CallSpawn Finds the spawn function for the entity and calls it, returning qfalse if not found =============== */ qboolean G_CallSpawn(gentity_t *ent) { spawn_t *s; gitem_t *item; if (!ent->classname) { G_DPrintf("G_CallSpawn: NULL classname\n"); return qfalse; } // check item spawn functions for (item = bg_itemlist + 1 ; item->classname ; ++item) { if (!strcmp(item->classname, ent->classname)) { // found it G_SpawnItem(ent, item); G_Script_ScriptParse(ent); G_Script_ScriptEvent(ent, "spawn", ""); return qtrue; } } // check normal spawn functions for (s = spawns ; s->name ; ++s) { if (!strcmp(s->name, ent->classname)) { // found it s->spawn(ent); // RF, entity scripting if (ent->scriptName) { G_Script_ScriptParse(ent); G_Script_ScriptEvent(ent, "spawn", ""); } return qtrue; } } G_DPrintf("%s doesn't have a spawn function\n", ent->classname); return qfalse; }
void Touch_flagonly_multiple(gentity_t *ent, gentity_t *other, trace_t *trace) { gentity_t *tmp; // Nico, silent GCC (void)trace; if (!other->client) { return; } if (ent->spawnflags & RED_FLAG && other->client->ps.powerups[PW_REDFLAG]) { other->client->ps.powerups[PW_REDFLAG] = 0; other->client->speedScale = 0; tmp = ent->parent; ent->parent = other; G_Script_ScriptEvent(ent, "death", ""); G_Script_ScriptEvent(&g_entities[other->client->flagParent], "trigger", "captured"); ent->parent = tmp; } else if (ent->spawnflags & BLUE_FLAG && other->client->ps.powerups[PW_BLUEFLAG]) { other->client->ps.powerups[PW_BLUEFLAG] = 0; other->client->speedScale = 0; tmp = ent->parent; ent->parent = other; G_Script_ScriptEvent(ent, "death", ""); G_Script_ScriptEvent(&g_entities[other->client->flagParent], "trigger", "captured"); ent->parent = tmp; } }
void script_mover_use(gentity_t *ent, gentity_t *other, gentity_t *activator) { if(ent->spawnflags & 8) { if(ent->count) { ent->health = ent->count; ent->s.dl_intensity = ent->health; G_Script_ScriptEvent( ent, "rebirth", "" ); ent->die = script_mover_die; } } else { script_mover_spawn(ent); } }
/* QUAKED target_script_trigger (1 .7 .2) (-8 -8 -8) (8 8 8) must have an aiName must have a target when used it will fire its targets */ void target_script_trigger_use(gentity_t *ent, gentity_t *other, gentity_t *activator) { qboolean found = qfalse; // for all entities/bots with this ainame gentity_t *trent = NULL; // Are we using ainame to find another ent instead of using scriptname for this one? if (ent->aiName) { // Find the first entity with this name trent = G_Find(trent, FOFS(scriptName), ent->aiName); // Was there one? if (trent) { // We found it found = qtrue; // Play the script G_Script_ScriptEvent(trent, "trigger", ent->target); } // if (trent)... } // if (ent->aiName)... // Use the old method if we didn't find an entity with the ainame if (!found) { if (ent->scriptName) { G_Script_ScriptEvent(ent, "trigger", ent->target); } } G_UseTargets(ent, other); }
/*QUAKED target_script_trigger (1 .7 .2) (-8 -8 -8) (8 8 8) must have an aiName must have a target when used it will fire its targets */ void target_script_trigger_use (gentity_t *ent, gentity_t *other, gentity_t *activator ) { gentity_t *player; if (ent->aiName) { player = AICast_FindEntityForName("player"); if (player) AICast_ScriptEvent( AICast_GetCastState(player->s.number), "trigger", ent->target ); } // DHM - Nerve :: In multiplayer, we use the brush scripting only if ( g_gametype.integer >= GT_WOLF && ent->scriptName ) { G_Script_ScriptEvent( ent, "trigger", ent->target ); } G_UseTargets ( ent, other); }
/* ================= G_ScriptAction_Trigger syntax: trigger <aiName/scriptName> <trigger> Calls the specified trigger for the given ai character or script entity ================= */ qboolean G_ScriptAction_Trigger( gentity_t *ent, char *params ) { gentity_t *trent; char *pString, name[MAX_QPATH], trigger[MAX_QPATH], *token; int oldId; // get the cast name pString = params; token = COM_ParseExt( &pString, qfalse ); Q_strncpyz( name, token, sizeof(name) ); if (!name[0]) { G_Error( "G_Scripting: trigger must have a name and an identifier\n" ); } token = COM_ParseExt( &pString, qfalse ); Q_strncpyz( trigger, token, sizeof(trigger) ); if (!trigger[0]) { G_Error( "G_Scripting: trigger must have a name and an identifier\n" ); } // trent = AICast_FindEntityForName( name ); trent = NULL; if (trent) { // we are triggering an AI //oldId = trent->scriptStatus.scriptId; // AICast_ScriptEvent( AICast_GetCastState( trent->s.number ), "trigger", trigger ); return qtrue; } // look for an entity trent = G_Find( &g_entities[MAX_CLIENTS], FOFS(scriptName), name ); if (trent) { oldId = trent->scriptStatus.scriptId; G_Script_ScriptEvent( trent, "trigger", trigger ); // if the script changed, return false so we don't muck with it's variables return ((trent != ent) || (oldId == trent->scriptStatus.scriptId)); } G_Error( "G_Scripting: trigger has unknown name: %s\n", name ); return qfalse; // shutup the compiler }
void script_mover_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int mod ) { if ( self->spawnflags & 4 ) { switch ( mod ) { case MOD_GRENADE: case MOD_GRENADE_SPLASH: case MOD_ROCKET: case MOD_ROCKET_SPLASH: case MOD_AIRSTRIKE: break; default: // no death from this weapon self->health += damage; return; } } G_Script_ScriptEvent( self, "death", "" ); self->die = NULL; trap_UnlinkEntity( self ); G_FreeEntity( self ); }
/*QUAKED target_script_trigger (1 .7 .2) (-8 -8 -8) (8 8 8) must have an aiName must have a target when used it will fire its targets */ void target_script_trigger_use (gentity_t *ent, gentity_t *other, gentity_t *activator ) { // gentity_t *player; if (ent->aiName) { // player = AICast_FindEntityForName("player"); // if (player) // AICast_ScriptEvent( AICast_GetCastState(player->s.number), "trigger", ent->target ); } // DHM - Nerve :: In multiplayer, we use the brush scripting only if ( g_gametype.integer >= GT_WOLF && ent->scriptName ) { #ifdef OMNIBOT Bot_Util_SendTrigger(ent, NULL, ent->scriptName, ent->target ); #endif G_Script_ScriptEvent( ent, "trigger", ent->target ); } G_UseTargets ( ent, other); }
/* =============== G_CallSpawn Finds the spawn function for the entity and calls it, returning qfalse if not found =============== */ qboolean G_CallSpawn( gentity_t *ent ) { spawn_t *s; gitem_t *item; if ( !ent->classname ) { G_Printf( "G_CallSpawn: NULL classname\n" ); return qfalse; } // check item spawn functions for ( item = bg_itemlist + 1 ; item->classname ; item++ ) { if ( !strcmp( item->classname, ent->classname ) ) { // found it // DHM - Nerve :: allow flags in GTWOLF if ( item->giType == IT_TEAM && ( g_gametype.integer != GT_CTF && g_gametype.integer < GT_WOLF ) ) { return qfalse; } G_SpawnItem( ent, item ); return qtrue; } } // check normal spawn functions for ( s = spawns ; s->name ; s++ ) { if ( !strcmp( s->name, ent->classname ) ) { // found it s->spawn( ent ); // RF, entity scripting if ( ent->s.number >= MAX_CLIENTS && ent->scriptName ) { G_Script_ScriptParse( ent ); G_Script_ScriptEvent( ent, "spawn", "" ); } return qtrue; } } G_Printf( "%s doesn't have a spawn function\n", ent->classname ); return qfalse; }
// the trigger was just activated // ent->activator should be set to the activator so it can be held through a delay // so wait for the delay time before firing // Nico, note: ent->random is effect less on this entity void multi_trigger(gentity_t *ent, gentity_t *activator) { ent->activator = activator; G_Script_ScriptEvent(ent, "activate", NULL); // Nico, #todo: handle case when ent->triggerTime[activator->client->ps.clientNum] = 0 if (ent->wait > 0) { if (activator->client && ent->triggerTime[activator->client->ps.clientNum] + ent->wait * 1000 > level.time) { // Client has to wait before triggering this entity! return; } G_UseTargets(ent, ent->activator); if (activator->client) { ent->triggerTime[activator->client->ps.clientNum] = level.time; } } else { // Nico, #todo: update ent->triggerTime[activator->client->ps.clientNum]??? G_UseTargets(ent, ent->activator); // we can't just remove (self) here, because this is a touch function // called while looping through area links... ent->touch = 0; ent->nextthink = level.time + FRAMETIME; ent->think = G_FreeEntity; } }
void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker, vec3_t dir, vec3_t point, int damage, int dflags, int mod ) { gclient_t *client; int take; int save; int asave; int knockback; if ( !targ->takedamage ) { return; } // the intermission has allready been qualified for, so don't // allow any extra scoring if ( level.intermissionQueued || g_gamestate.integer != GS_PLAYING ) { return; } if ( !inflictor ) { inflictor = &g_entities[ENTITYNUM_WORLD]; } if ( !attacker ) { attacker = &g_entities[ENTITYNUM_WORLD]; } // JPW NERVE if ( ( targ->waterlevel >= 3 ) && ( mod == MOD_FLAMETHROWER ) ) { return; } // jpw // shootable doors / buttons don't actually have any health if ( targ->s.eType == ET_MOVER && !( targ->aiName ) && !( targ->isProp ) && !targ->scriptName ) { if ( targ->use && targ->moverState == MOVER_POS1 ) { targ->use( targ, inflictor, attacker ); } return; } if ( targ->s.eType == ET_MOVER && targ->aiName && !( targ->isProp ) && !targ->scriptName ) { switch ( mod ) { case MOD_GRENADE: case MOD_GRENADE_SPLASH: case MOD_ROCKET: case MOD_ROCKET_SPLASH: break; default: return; // no damage from other weapons } } else if ( targ->s.eType == ET_EXPLOSIVE ) { // 32 Explosive // 64 Dynamite only if ( ( targ->spawnflags & 32 ) || ( targ->spawnflags & 64 ) ) { switch ( mod ) { case MOD_GRENADE: case MOD_GRENADE_SPLASH: case MOD_ROCKET: case MOD_ROCKET_SPLASH: case MOD_AIRSTRIKE: case MOD_GRENADE_PINEAPPLE: case MOD_MORTAR: case MOD_MORTAR_SPLASH: case MOD_EXPLOSIVE: if ( targ->spawnflags & 64 ) { return; } break; case MOD_DYNAMITE: case MOD_DYNAMITE_SPLASH: break; default: return; } } } client = targ->client; if ( client ) { if ( client->noclip ) { return; } } if ( !dir ) { dflags |= DAMAGE_NO_KNOCKBACK; } else { VectorNormalize( dir ); } knockback = damage; if ( knockback > 200 ) { knockback = 200; } if ( targ->flags & FL_NO_KNOCKBACK ) { knockback = 0; } if ( dflags & DAMAGE_NO_KNOCKBACK ) { knockback = 0; } // figure momentum add, even if the damage won't be taken if ( knockback && targ->client && ( g_friendlyFire.integer || !OnSameTeam( targ, attacker ) ) ) { vec3_t kvel; float mass; mass = 200; if ( mod == MOD_LIGHTNING && !( ( level.time + targ->s.number * 50 ) % 400 ) ) { knockback = 60; dir[2] = 0.3; } VectorScale( dir, g_knockback.value * (float)knockback / mass, kvel ); VectorAdd( targ->client->ps.velocity, kvel, targ->client->ps.velocity ); if ( targ == attacker && !( mod != MOD_ROCKET && mod != MOD_ROCKET_SPLASH && mod != MOD_GRENADE && mod != MOD_GRENADE_SPLASH && mod != MOD_DYNAMITE ) ) { targ->client->ps.velocity[2] *= 0.25; } // set the timer so that the other client can't cancel // out the movement immediately if ( !targ->client->ps.pm_time ) { int t; t = knockback * 2; if ( t < 50 ) { t = 50; } if ( t > 200 ) { t = 200; } targ->client->ps.pm_time = t; targ->client->ps.pm_flags |= PMF_TIME_KNOCKBACK; } } // check for completely getting out of the damage if ( !( dflags & DAMAGE_NO_PROTECTION ) ) { // if TF_NO_FRIENDLY_FIRE is set, don't do damage to the target // if the attacker was on the same team if ( targ != attacker && OnSameTeam( targ, attacker ) ) { if ( !g_friendlyFire.integer ) { return; } } // check for godmode if ( targ->flags & FL_GODMODE ) { return; } // RF, warzombie defense position is basically godmode for the time being if ( targ->flags & FL_DEFENSE_GUARD ) { return; } // check for invulnerability // (SA) moved from below so DAMAGE_NO_PROTECTION will still work if ( client && client->ps.powerups[PW_INVULNERABLE] ) { //----(SA) added return; } } // battlesuit protects from all radius damage (but takes knockback) // and protects 50% against all damage if ( client && client->ps.powerups[PW_BATTLESUIT] ) { G_AddEvent( targ, EV_POWERUP_BATTLESUIT, 0 ); if ( dflags & DAMAGE_RADIUS ) { return; } damage *= 0.5; } // add to the attacker's hit counter if ( attacker->client && targ != attacker && targ->health > 0 ) { if ( OnSameTeam( targ, attacker ) ) { attacker->client->ps.persistant[PERS_HITS] -= damage; } else { attacker->client->ps.persistant[PERS_HITS] += damage; } } if ( damage < 1 ) { damage = 1; } take = damage; save = 0; // save some from armor asave = CheckArmor( targ, take, dflags ); take -= asave; if ( IsHeadShot( targ, qfalse, dir, point, mod ) ) { if ( take * 2 < 50 ) { // head shots, all weapons, do minimum 50 points damage take = 50; } else { take *= 2; // sniper rifles can do full-kill (and knock into limbo) } if ( !( targ->client->ps.eFlags & EF_HEADSHOT ) ) { // only toss hat on first headshot G_AddEvent( targ, EV_LOSE_HAT, DirToByte( dir ) ); } targ->client->ps.eFlags |= EF_HEADSHOT; } if ( g_debugDamage.integer ) { G_Printf( "client:%i health:%i damage:%i armor:%i\n", targ->s.number, targ->health, take, asave ); } // add to the damage inflicted on a player this frame // the total will be turned into screen blends and view angle kicks // at the end of the frame if ( client ) { if ( attacker ) { client->ps.persistant[PERS_ATTACKER] = attacker->s.number; } else { client->ps.persistant[PERS_ATTACKER] = ENTITYNUM_WORLD; } client->damage_armor += asave; client->damage_blood += take; client->damage_knockback += knockback; if ( dir ) { VectorCopy( dir, client->damage_from ); client->damage_fromWorld = qfalse; } else { VectorCopy( targ->r.currentOrigin, client->damage_from ); client->damage_fromWorld = qtrue; } } // See if it's the player hurting the emeny flag carrier Team_CheckHurtCarrier( targ, attacker ); if ( targ->client ) { // set the last client who damaged the target targ->client->lasthurt_client = attacker->s.number; targ->client->lasthurt_mod = mod; } // do the damage if ( take ) { targ->health = targ->health - take; // Ridah, can't gib with bullet weapons (except VENOM) if ( mod != MOD_VENOM && attacker == inflictor && targ->health <= GIB_HEALTH ) { if ( targ->aiCharacter != AICHAR_ZOMBIE ) { // zombie needs to be able to gib so we can kill him (although he doesn't actually GIB, he just dies) targ->health = GIB_HEALTH + 1; } } // JPW NERVE overcome previous chunk of code for making grenades work again if ( ( g_gametype.integer != GT_SINGLE_PLAYER ) && ( take > 190 ) ) { // 190 is greater than 2x mauser headshot, so headshots don't gib targ->health = GIB_HEALTH - 1; } // jpw //G_Printf("health at: %d\n", targ->health); if ( targ->health <= 0 ) { if ( client ) { targ->flags |= FL_NO_KNOCKBACK; // JPW NERVE -- repeated shooting sends to limbo if ( g_gametype.integer >= GT_WOLF ) { if ( ( targ->health < FORCE_LIMBO_HEALTH ) && ( targ->health > GIB_HEALTH ) && ( !( targ->client->ps.pm_flags & PMF_LIMBO ) ) ) { limbo( targ, qtrue ); } } // jpw } if ( targ->health < -999 ) { targ->health = -999; } targ->enemy = attacker; if ( targ->die ) { // Ridah, mg42 doesn't have die func (FIXME) targ->die( targ, inflictor, attacker, take, mod ); } // if we freed ourselves in death function if ( !targ->inuse ) { return; } // RF, entity scripting if ( targ->s.number >= MAX_CLIENTS && targ->health <= 0 ) { // might have revived itself in death function G_Script_ScriptEvent( targ, "death", "" ); } } else if ( targ->pain ) { if ( dir ) { // Ridah, had to add this to fix NULL dir crash VectorCopy( dir, targ->rotate ); VectorCopy( point, targ->pos3 ); // this will pass loc of hit } else { VectorClear( targ->rotate ); VectorClear( targ->pos3 ); } targ->pain( targ, attacker, take, point ); // RF, entity scripting if ( targ->s.number >= MAX_CLIENTS ) { G_Script_ScriptEvent( targ, "pain", va( "%d %d", targ->health, targ->health + take ) ); } } //G_ArmorDamage(targ); //----(SA) moved out to separate routine // Ridah, this needs to be done last, incase the health is altered in one of the event calls if ( targ->client ) { targ->client->ps.stats[STAT_HEALTH] = targ->health; } } }
void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker, vec3_t dir, vec3_t point, int damage, int dflags, int mod ) { gclient_t *client; int take; int save; int knockback; qboolean headShot; qboolean wasAlive; hitRegion_t hr = HR_NUM_HITREGIONS; if (!targ->takedamage) { return; } #ifdef SAVEGAME_SUPPORT if( g_gametype.integer == GT_SINGLE_PLAYER && ( g_reloading.integer || saveGamePending ) ) return; #endif // SAVEGAME_SUPPORT // trap_SendServerCommand( -1, va("print \"%i\n\"\n", targ->health) ); // the intermission has allready been qualified for, so don't // allow any extra scoring if ( level.intermissionQueued || (g_gamestate.integer != GS_PLAYING && match_warmupDamage.integer == 0)) { return; } if ( !inflictor ) { inflictor = &g_entities[ENTITYNUM_WORLD]; } if ( !attacker ) { attacker = &g_entities[ENTITYNUM_WORLD]; } // Arnout: invisible entities can't be damaged if( targ->entstate == STATE_INVISIBLE || targ->entstate == STATE_UNDERCONSTRUCTION ) { return; } // xkan, 12/23/2002 - was the bot alive before applying any damage? wasAlive = (targ->health > 0); // Arnout: combatstate if( targ->client && attacker && attacker->client && attacker != targ ) { /*vec_t dist = -1.f; if( targ->client->combatState < COMBATSTATE_HOT ) { vec3_t shotvec; VectorSubtract( targ->r.currentOrigin, attacker->r.currentOrigin, shotvec ); dist = VectorLengthSquared( shotvec ); if( dist < Square(1500.f) && targ->client->combatState == COMBATSTATE_WARM ) targ->client->combatState = COMBATSTATE_HOT; } if( attacker->client->combatState < COMBATSTATE_HOT ) { if( dist < 0.f ) { vec3_t shotvec; VectorSubtract( targ->r.currentOrigin, attacker->r.currentOrigin, shotvec ); dist = VectorLengthSquared( shotvec ); } if( dist > Square(1500.f) ) attacker->client->combatState = COMBATSTATE_WARM; else if( attacker->client->combatState == COMBATSTATE_WARM ) attacker->client->combatState = COMBATSTATE_HOT; }*/ if( g_gamestate.integer == GS_PLAYING ) { if( !OnSameTeam( attacker, targ ) ) { targ->client->combatState |= (1<<COMBATSTATE_DAMAGERECEIVED); attacker->client->combatState |= (1<<COMBATSTATE_DAMAGEDEALT); } } } // JPW NERVE if ((targ->waterlevel >= 3) && (mod == MOD_FLAMETHROWER)) return; // jpw // shootable doors / buttons don't actually have any health if ( targ->s.eType == ET_MOVER && !(targ->isProp) && !targ->scriptName) { if ( targ->use && targ->moverState == MOVER_POS1 ) { G_UseEntity( targ, inflictor, attacker ); } return; } // TAT 11/22/2002 // In the old code, this check wasn't done for props, so I put that check back in to make props_statue properly work // 4 means destructible if ( targ->s.eType == ET_MOVER && (targ->spawnflags & 4) && !targ->isProp ) { /*switch (mod) { case MOD_GRENADE: case MOD_GRENADE_LAUNCHER: case MOD_ROCKET: case MOD_AIRSTRIKE: case MOD_ARTY: case MOD_GRENADE_PINEAPPLE: case MOD_MAPMORTAR: case MOD_EXPLOSIVE: case MOD_DYNAMITE: case MOD_LANDMINE: case MOD_GPG40: case MOD_M7: case MOD_TELEFRAG: case MOD_PANZERFAUST: case MOD_SATCHEL: break; default: return; // no damage from other weapons }*/ if( !G_WeaponIsExplosive( mod ) ) { return; } // check for team if( G_GetTeamFromEntity( inflictor ) == G_GetTeamFromEntity( targ ) ) { return; } } else if ( targ->s.eType == ET_EXPLOSIVE ) { /*// 32 Explosive // 64 Dynamite only // 256 Airstrike/artillery only // 512 Satchel only if ((targ->spawnflags & 32) || (targ->spawnflags & 64) || (targ->spawnflags & 256) || (targ->spawnflags & 512)) { switch (mod) { case MOD_GRENADE: case MOD_GRENADE_LAUNCHER: case MOD_ROCKET: case MOD_GRENADE_PINEAPPLE: case MOD_MAPMORTAR: case MOD_EXPLOSIVE: case MOD_LANDMINE: case MOD_GPG40: case MOD_M7: if( !(targ->spawnflags & 32) ) return; break; case MOD_SATCHEL: if( !(targ->spawnflags & 512) ) return; break; case MOD_ARTY: case MOD_AIRSTRIKE: if( !(targ->spawnflags & 256) ) return; break; case MOD_DYNAMITE: if( !(targ->spawnflags & 64) ) return; break; default: return; } // check for team if( targ->s.teamNum == inflictor->s.teamNum ) { return; } }*/ if( targ->parent && G_GetWeaponClassForMOD( mod ) == 2 ) { return; } // check for team // if( G_GetWeaponClassForMOD( mod ) != -1 && targ->s.teamNum == inflictor->s.teamNum ) { // return; // } if( G_GetTeamFromEntity( inflictor ) == G_GetTeamFromEntity( targ ) ) { return; } if( G_GetWeaponClassForMOD( mod ) < targ->constructibleStats.weaponclass ) { return; } } else if ( targ->s.eType == ET_MISSILE && targ->methodOfDeath == MOD_LANDMINE ) { if( targ->s.modelindex2 ) { if( G_WeaponIsExplosive( mod ) ) { mapEntityData_t *mEnt; if((mEnt = G_FindMapEntityData(&mapEntityData[0], targ-g_entities)) != NULL) { G_FreeMapEntityData( &mapEntityData[0], mEnt ); } if((mEnt = G_FindMapEntityData(&mapEntityData[1], targ-g_entities)) != NULL) { G_FreeMapEntityData( &mapEntityData[1], mEnt ); } if( attacker && attacker->client ) { AddScore( attacker, 1 ); //G_AddExperience( attacker, 1.f ); } G_ExplodeMissile(targ); } } return; } else if ( targ->s.eType == ET_CONSTRUCTIBLE ) { if( G_GetTeamFromEntity( inflictor ) == G_GetTeamFromEntity( targ ) ) { return; } if( G_GetWeaponClassForMOD( mod ) < targ->constructibleStats.weaponclass ) { return; } } client = targ->client; if ( client ) { if ( client->noclip || client->ps.powerups[PW_INVULNERABLE] ) { return; } } // check for godmode if ( targ->flags & FL_GODMODE ) { return; } if ( !dir ) { dflags |= DAMAGE_NO_KNOCKBACK; } else { VectorNormalize(dir); } knockback = damage; if ( knockback > 200 ) { knockback = 200; } if ( targ->flags & FL_NO_KNOCKBACK ) { knockback = 0; } if ( dflags & DAMAGE_NO_KNOCKBACK ) { knockback = 0; } else if( dflags & DAMAGE_HALF_KNOCKBACK ) { knockback *= 0.5f; } // ydnar: set weapons means less knockback if( client && (client->ps.weapon == WP_MORTAR_SET || client->ps.weapon == WP_MOBILE_MG42_SET) ) knockback *= 0.5; if( targ->client && g_friendlyFire.integer && OnSameTeam(targ, attacker) ) { knockback = 0; } // figure momentum add, even if the damage won't be taken if ( knockback && targ->client ) { vec3_t kvel; float mass; mass = 200; VectorScale (dir, g_knockback.value * (float)knockback / mass, kvel); VectorAdd (targ->client->ps.velocity, kvel, targ->client->ps.velocity); /*if( mod == MOD_GRENADE || mod == MOD_GRENADE_LAUNCHER || mod == MOD_DYNAMITE || mod == MOD_GPG40 || mod == MOD_M7 || mod == MOD_LANDMINE ) { targ->client->ps.velocity[2] *= 2.f; // gimme air baby! targ->client->ps.groundEntityNum = ENTITYNUM_NONE; // flying high! } else if( mod == MOD_ROCKET ) { targ->client->ps.velocity[2] *= .75f; // but not to the moon please! targ->client->ps.groundEntityNum = ENTITYNUM_NONE; // flying high! }*/ if (targ == attacker && !( mod != MOD_ROCKET && mod != MOD_GRENADE && mod != MOD_GRENADE_LAUNCHER && mod != MOD_DYNAMITE && mod != MOD_GPG40 && mod != MOD_M7 && mod != MOD_LANDMINE )) { targ->client->ps.velocity[2] *= 0.25; } // set the timer so that the other client can't cancel // out the movement immediately if ( !targ->client->ps.pm_time ) { int t; t = knockback * 2; if ( t < 50 ) { t = 50; } if ( t > 200 ) { t = 200; } targ->client->ps.pm_time = t; targ->client->ps.pm_flags |= PMF_TIME_KNOCKBACK; } } // check for completely getting out of the damage if ( !(dflags & DAMAGE_NO_PROTECTION) ) { // if TF_NO_FRIENDLY_FIRE is set, don't do damage to the target // if the attacker was on the same team if ( targ != attacker && OnSameTeam (targ, attacker) ) { if ( (g_gamestate.integer != GS_PLAYING && match_warmupDamage.integer == 1)) { return; } else if (!g_friendlyFire.integer) { return; } } } // add to the attacker's hit counter if ( attacker->client && targ != attacker && targ->health > 0 ) { if ( OnSameTeam( targ, attacker ) ) { attacker->client->ps.persistant[PERS_HITS] -= damage; } else { attacker->client->ps.persistant[PERS_HITS] += damage; } } if ( damage < 1 ) { damage = 1; } take = damage; save = 0; // adrenaline junkie! if( targ->client && targ->client->ps.powerups[PW_ADRENALINE] ) { take *= .5f; } // save some from flak jacket if( targ->client && targ->client->sess.skill[SK_EXPLOSIVES_AND_CONSTRUCTION] >= 4 && targ->client->sess.playerType == PC_ENGINEER ) { if( mod == MOD_GRENADE || mod == MOD_GRENADE_LAUNCHER || mod == MOD_ROCKET || mod == MOD_GRENADE_PINEAPPLE || mod == MOD_MAPMORTAR || mod == MOD_MAPMORTAR_SPLASH || mod == MOD_EXPLOSIVE || mod == MOD_LANDMINE || mod == MOD_GPG40 || mod == MOD_M7 || mod == MOD_SATCHEL || mod == MOD_ARTY || mod == MOD_AIRSTRIKE || mod == MOD_DYNAMITE || mod == MOD_MORTAR || mod == MOD_PANZERFAUST || mod == MOD_MAPMORTAR ) { take -= take * .5f; } } headShot = IsHeadShot(targ, dir, point, mod); if ( headShot ) { if( take * 2 < 50 ) // head shots, all weapons, do minimum 50 points damage take = 50; else take *= 2; // sniper rifles can do full-kill (and knock into limbo) if( dflags & DAMAGE_DISTANCEFALLOFF ) { vec_t dist; vec3_t shotvec; VectorSubtract( point, muzzleTrace, shotvec ); dist = VectorLength( shotvec ); if( dist > 1500.f ) { if( dist > 2500.f ) { take *= 0.2f; } else { float scale = 1.f - 0.2f * (1000.f / (dist - 1000.f)); take *= scale; } } } if( !(targ->client->ps.eFlags & EF_HEADSHOT) ) { // only toss hat on first headshot G_AddEvent( targ, EV_LOSE_HAT, DirToByte(dir) ); if( mod != MOD_K43_SCOPE && mod != MOD_GARAND_SCOPE ) { take *= .8f; // helmet gives us some protection } } targ->client->ps.eFlags |= EF_HEADSHOT; // OSP - Record the headshot if(client && attacker && attacker->client #ifndef DEBUG_STATS && attacker->client->sess.sessionTeam != targ->client->sess.sessionTeam #endif ) { G_addStatsHeadShot(attacker, mod); } if( g_debugBullets.integer ) { trap_SendServerCommand( attacker-g_entities, "print \"Head Shot\n\"\n"); } G_LogRegionHit( attacker, HR_HEAD ); hr = HR_HEAD; } else if ( IsLegShot(targ, dir, point, mod) ) { G_LogRegionHit( attacker, HR_LEGS ); hr = HR_LEGS; if( g_debugBullets.integer ) { trap_SendServerCommand( attacker-g_entities, "print \"Leg Shot\n\"\n"); } } else if ( IsArmShot(targ, attacker, point, mod) ) { G_LogRegionHit( attacker, HR_ARMS ); hr = HR_ARMS; if( g_debugBullets.integer ) { trap_SendServerCommand( attacker-g_entities, "print \"Arm Shot\n\"\n"); } } else if (targ->client && targ->health > 0 && IsHeadShotWeapon( mod ) ) { G_LogRegionHit( attacker, HR_BODY ); hr = HR_BODY; if( g_debugBullets.integer ) { trap_SendServerCommand( attacker-g_entities, "print \"Body Shot\n\"\n"); } } #ifndef DEBUG_STATS if ( g_debugDamage.integer ) #endif { G_Printf( "client:%i health:%i damage:%i mod:%s\n", targ->s.number, targ->health, take, modNames[mod] ); } // add to the damage inflicted on a player this frame // the total will be turned into screen blends and view angle kicks // at the end of the frame if ( client ) { if ( attacker ) { client->ps.persistant[PERS_ATTACKER] = attacker->s.number; } else { client->ps.persistant[PERS_ATTACKER] = ENTITYNUM_WORLD; } client->damage_blood += take; client->damage_knockback += knockback; if ( dir ) { VectorCopy ( dir, client->damage_from ); client->damage_fromWorld = qfalse; } else { VectorCopy ( targ->r.currentOrigin, client->damage_from ); client->damage_fromWorld = qtrue; } } // See if it's the player hurting the emeny flag carrier // Team_CheckHurtCarrier(targ, attacker); if (targ->client) { // set the last client who damaged the target targ->client->lasthurt_client = attacker->s.number; targ->client->lasthurt_mod = mod; } // do the damage if( take ) { targ->health -= take; // Gordon: don't ever gib POWS if( ( targ->health <= 0 ) && ( targ->r.svFlags & SVF_POW ) ) { targ->health = -1; } // Ridah, can't gib with bullet weapons (except VENOM) // Arnout: attacker == inflictor can happen in other cases as well! (movers trying to gib things) //if ( attacker == inflictor && targ->health <= GIB_HEALTH) { if( targ->health <= GIB_HEALTH ) { if( !G_WeaponIsExplosive( mod ) ) { targ->health = GIB_HEALTH + 1; } } // JPW NERVE overcome previous chunk of code for making grenades work again // if ((take > 190)) // 190 is greater than 2x mauser headshot, so headshots don't gib // Arnout: only player entities! messes up ents like func_constructibles and func_explosives otherwise if( ( (targ->s.number < MAX_CLIENTS) && (take > 190) ) && !(targ->r.svFlags & SVF_POW) ) { targ->health = GIB_HEALTH - 1; } if( targ->s.eType == ET_MOVER && !Q_stricmp( targ->classname, "script_mover" ) ) { targ->s.dl_intensity = 255.f * (targ->health / (float)targ->count); // send it to the client } //G_Printf("health at: %d\n", targ->health); if( targ->health <= 0 ) { if( client && !wasAlive ) { targ->flags |= FL_NO_KNOCKBACK; // OSP - special hack to not count attempts for body gibbage if( targ->client->ps.pm_type == PM_DEAD ) { G_addStats(targ, attacker, take, mod); } if( (targ->health < FORCE_LIMBO_HEALTH) && (targ->health > GIB_HEALTH) ) { limbo(targ, qtrue); } // xkan, 1/13/2003 - record the time we died. if (!client->deathTime) client->deathTime = level.time; } else { targ->sound1to2 = hr; targ->sound2to1 = mod; targ->sound2to3 = (dflags & DAMAGE_RADIUS) ? 1 : 0; if( client ) { if( G_GetTeamFromEntity( inflictor ) != G_GetTeamFromEntity( targ ) ) { G_AddKillSkillPoints( attacker, mod, hr, (dflags & DAMAGE_RADIUS) ); } } if( targ->health < -999 ) { targ->health = -999; } targ->enemy = attacker; targ->deathType = mod; // Ridah, mg42 doesn't have die func (FIXME) if( targ->die ) { // Kill the entity. Note that this funtion can set ->die to another // function pointer, so that next time die is applied to the dead body. targ->die( targ, inflictor, attacker, take, mod ); // OSP - kill stats in player_die function } if( targ->s.eType == ET_MOVER && !Q_stricmp( targ->classname, "script_mover" ) && (targ->spawnflags & 8) ) { return; // reseructable script mover doesn't unlink itself but we don't want a second death script to be called } // if we freed ourselves in death function if (!targ->inuse) return; // RF, entity scripting if (targ->health <= 0) { // might have revived itself in death function if ((targ->s.eType != ET_CONSTRUCTIBLE && targ->s.eType != ET_EXPLOSIVE) || (targ->s.eType == ET_CONSTRUCTIBLE && !targ->desstages)) { // call manually if using desstages G_Script_ScriptEvent( targ, "death", "" ); } } } } else if ( targ->pain ) { if (dir) { // Ridah, had to add this to fix NULL dir crash VectorCopy (dir, targ->rotate); VectorCopy (point, targ->pos3); // this will pass loc of hit } else { VectorClear( targ->rotate ); VectorClear( targ->pos3 ); } targ->pain (targ, attacker, take, point); } else { // OSP - update weapon/dmg stats G_addStats(targ, attacker, take, mod); // OSP } // RF, entity scripting G_Script_ScriptEvent( targ, "pain", va("%d %d", targ->health, targ->health+take) ); // Ridah, this needs to be done last, incase the health is altered in one of the event calls if ( targ->client ) { targ->client->ps.stats[STAT_HEALTH] = targ->health; } } }