// 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->nextthink) { return; // can't retrigger until the wait is over } if(activator->client) { if(ent->red_only && activator->client->sess.sessionTeam != TEAM_RED) { return; } if(ent->blue_only && activator->client->sess.sessionTeam != TEAM_BLUE) { return; } } G_UseTargets(ent, ent->activator); #ifdef G_LUA // Lua API callbacks if(ent->luaTrigger) { if(activator) { G_LuaHook_EntityTrigger(ent->luaTrigger, ent->s.number, activator->s.number); } else { G_LuaHook_EntityTrigger(ent->luaTrigger, ent->s.number, ENTITYNUM_WORLD); } } #endif 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 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->spawnflags & 16) self->timestamp = level.time + 1000; else self->timestamp = level.time + FRAMETIME; // play sound if(!(self->spawnflags & 4)) G_Sound(other, CHAN_AUTO, self->soundIndex); #ifdef G_LUA // Lua API callbacks if(self->luaTrigger) { G_LuaHook_EntityTrigger(self->luaTrigger, self->s.number, other->s.number); } #endif if(self->spawnflags & 8) dflags = DAMAGE_NO_PROTECTION; else dflags = 0; G_Damage(other, self, self, NULL, NULL, self->damage, dflags, MOD_TRIGGER_HURT); }
void trigger_teleporter_touch(gentity_t * self, gentity_t * other, trace_t * trace) { gentity_t *dest; if(!other->client) return; if(other->client->ps.pm_type == PM_DEAD) return; // Spectators only? if((self->spawnflags & 1) && other->client->sess.sessionTeam != TEAM_SPECTATOR) return; dest = G_PickTarget(self->target); if(!dest) { G_Printf("Couldn't find teleporter destination\n"); return; } #ifdef G_LUA // Lua API callbacks if(self->luaTrigger) { G_LuaHook_EntityTrigger(self->luaTrigger, self->s.number, other->s.number); } #endif TeleportPlayer(other, dest->s.origin, dest->s.angles); }
void Use_target_push(gentity_t * self, gentity_t * other, gentity_t * activator) { if(!activator->client) return; if(activator->client->ps.pm_type != PM_NORMAL) return; #ifdef G_LUA // Lua API callbacks if(self->luaTrigger) { G_LuaHook_EntityTrigger(self->luaTrigger, self->s.number, activator->s.number); } #endif VectorCopy(self->s.origin2, activator->client->ps.velocity); // play fly sound every 1.5 seconds if(activator->fly_sound_debounce_time < level.time) { activator->fly_sound_debounce_time = level.time + 1500; G_Sound(activator, CHAN_AUTO, self->soundIndex); } }
static void target_fx_think(gentity_t * self) { #ifdef G_LUA // Lua API callbacks if(self->luaTrigger) { G_LuaHook_EntityTrigger(self->luaTrigger, self->s.number, self->s.number); } #endif G_AddEvent(self, EV_EFFECT, self->s.modelindex); if(self->wait > 0) { //ent->think = multi_wait; self->nextthink = level.time + (self->wait + self->random * crandom()) * 1000; } else { // we can't just remove (self) here, because this is a touch function // called while looping through area links... self->touch = NULL; self->nextthink = level.time + FRAMETIME; self->think = G_FreeEntity; } }
// 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->nextthink) return; // can't retrigger until the wait is over if(activator->client) { if((ent->spawnflags & 1) && activator->client->ps.stats[STAT_PTEAM] != PTE_HUMANS) return; if((ent->spawnflags & 2) && activator->client->ps.stats[STAT_PTEAM] != PTE_ALIENS) return; } G_UseTargets(ent, ent->activator); #ifdef G_LUA // Lua API callbacks if(ent->luaTrigger) { if(activator) { G_LuaHook_EntityTrigger(ent->luaTrigger, ent->s.number, activator->s.number); } else { G_LuaHook_EntityTrigger(ent->luaTrigger, ent->s.number, ENTITYNUM_WORLD); } } #endif 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; } }
/*QUAKED target_delay (1 0 0) (-8 -8 -8) (8 8 8) "wait" seconds to pause before firing targets. "random" delay variance, total delay = delay +/- random seconds */ void Think_Target_Delay(gentity_t * ent) { #ifdef G_LUA // Lua API callbacks if(ent->luaTrigger) { if(ent->activator) { G_LuaHook_EntityTrigger(ent->luaTrigger, ent->s.number, ent->activator->s.number); } else { G_LuaHook_EntityTrigger(ent->luaTrigger, ent->s.number, ENTITYNUM_WORLD); } } #endif G_UseTargets(ent, ent->activator); }
/*QUAKED func_timer (0.3 0.1 0.6) (-8 -8 -8) (8 8 8) START_ON This should be renamed trigger_timer... Repeatedly fires its targets. Can be turned on or off by using. "wait" base time between triggering all targets, default is 1 "random" wait variance, default is 0 so, the basic time between firing is a random time between (wait - random) and (wait + random) */ void func_timer_think(gentity_t * self) { G_UseTargets(self, self->activator); #ifdef G_LUA // Lua API callbacks if(self->luaTrigger) { if(self->activator) { G_LuaHook_EntityTrigger(self->luaTrigger, self->s.number, self->activator->s.number); } else { G_LuaHook_EntityTrigger(self->luaTrigger, self->s.number, self->s.number); } } #endif // set time before next firing self->nextthink = level.time + 1000 * (self->wait + crandom() * self->random); }
void trigger_push_touch(gentity_t * self, gentity_t * other, trace_t * trace) { if(!other->client) return; #ifdef G_LUA // Lua API callbacks if(self->luaTrigger) { G_LuaHook_EntityTrigger(self->luaTrigger, self->s.number, other->s.number); } #endif }
void trigger_always_think(gentity_t * ent) { G_UseTargets(ent, ent); #ifdef G_LUA // Lua API callbacks if(ent->luaTrigger) { G_LuaHook_EntityTrigger(ent->luaTrigger, ent->s.number, ent->s.number); } #endif G_FreeEntity(ent); }
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->slow) { self->timestamp = level.time + 1000; } else { self->timestamp = level.time + FRAMETIME; } // play sound if(!self->silent) { G_Sound(other, CHAN_AUTO, self->soundIndex); } #ifdef G_LUA // Lua API callbacks if(self->luaTrigger) { G_LuaHook_EntityTrigger(self->luaTrigger, self->s.number, other->s.number); } #endif if(self->no_protection) dflags = DAMAGE_NO_PROTECTION; else dflags = 0; G_Damage(other, self, self, NULL, NULL, self->damage, dflags, MOD_TRIGGER_HURT); }
/* =========== ClientSpawn Called every time a client is placed fresh in the world: after the first ClientBegin, and after each respawn Initializes all non-persistant parts of playerState ============ */ void ClientSpawn(gentity_t * ent) { int index; vec3_t spawn_origin, spawn_angles; gclient_t *client; int i; clientPersistant_t saved; clientSession_t savedSess; int persistant[MAX_PERSISTANT]; gentity_t *spawnPoint; int flags; int savedPing; // char *savedAreaBits; int accuracy_hits, accuracy_shots; int eventSequence; char userinfo[MAX_INFO_STRING]; index = ent - g_entities; client = ent->client; // find a spawn point // do it before setting health back up, so farthest // ranging doesn't count this client if(client->sess.sessionTeam == TEAM_SPECTATOR) { spawnPoint = SelectSpectatorSpawnPoint(spawn_origin, spawn_angles); } else if(g_gametype.integer >= GT_CTF) { // all base oriented team games use the CTF spawn points spawnPoint = SelectCTFSpawnPoint(client->sess.sessionTeam, client->pers.teamState.state, spawn_origin, spawn_angles); } else { do { // the first spawn should be at a good looking spot if(!client->pers.initialSpawn && client->pers.localClient) { client->pers.initialSpawn = qtrue; spawnPoint = SelectInitialSpawnPoint(spawn_origin, spawn_angles); } else { // don't spawn near existing origin if possible spawnPoint = SelectSpawnPoint(client->ps.origin, spawn_origin, spawn_angles); } // Tim needs to prevent bots from spawning at the initial point // on q3dm0... if((spawnPoint->flags & FL_NO_BOTS) && (ent->r.svFlags & SVF_BOT)) { continue; // try again } // just to be symetric, we have a nohumans option... if((spawnPoint->flags & FL_NO_HUMANS) && !(ent->r.svFlags & SVF_BOT)) { continue; // try again } break; } while(1); } client->pers.teamState.state = TEAM_ACTIVE; // always clear the kamikaze flag ent->s.eFlags &= ~EF_KAMIKAZE; // toggle the teleport bit so the client knows to not lerp // and never clear the voted flag flags = ent->client->ps.eFlags & (EF_TELEPORT_BIT | EF_VOTED | EF_TEAMVOTED); flags ^= EF_TELEPORT_BIT; // clear everything but the persistant data saved = client->pers; savedSess = client->sess; savedPing = client->ps.ping; // savedAreaBits = client->areabits; accuracy_hits = client->accuracy_hits; accuracy_shots = client->accuracy_shots; for(i = 0; i < MAX_PERSISTANT; i++) { persistant[i] = client->ps.persistant[i]; } eventSequence = client->ps.eventSequence; Com_Memset(client, 0, sizeof(*client)); client->pers = saved; client->sess = savedSess; client->ps.ping = savedPing; // client->areabits = savedAreaBits; client->accuracy_hits = accuracy_hits; client->accuracy_shots = accuracy_shots; client->lastkilled_client = -1; for(i = 0; i < MAX_PERSISTANT; i++) { client->ps.persistant[i] = persistant[i]; } client->ps.eventSequence = eventSequence; // increment the spawncount so the client will detect the respawn client->ps.persistant[PERS_SPAWN_COUNT]++; client->ps.persistant[PERS_TEAM] = client->sess.sessionTeam; client->airOutTime = level.time + 12000; trap_GetUserinfo(index, userinfo, sizeof(userinfo)); // set max health client->pers.maxHealth = atoi(Info_ValueForKey(userinfo, "handicap")); if(client->pers.maxHealth < 1 || client->pers.maxHealth > 100) { client->pers.maxHealth = 100; } // clear entity values client->ps.stats[STAT_MAX_HEALTH] = client->pers.maxHealth; client->ps.eFlags = flags; ent->s.groundEntityNum = ENTITYNUM_NONE; ent->client = &level.clients[index]; ent->takedamage = qtrue; ent->inuse = qtrue; ent->classname = "player"; ent->r.contents = CONTENTS_BODY; ent->clipmask = MASK_PLAYERSOLID; ent->die = player_die; ent->waterlevel = 0; ent->watertype = 0; ent->flags = 0; VectorCopy(playerMins, ent->r.mins); VectorCopy(playerMaxs, ent->r.maxs); client->ps.clientNum = index; /* client->ps.stats[STAT_WEAPONS] = (1 << WP_MACHINEGUN); if(g_gametype.integer == GT_TEAM) { client->ps.ammo[WP_MACHINEGUN] = 50; } else { client->ps.ammo[WP_MACHINEGUN] = 100; } */ /* client->ps.stats[STAT_WEAPONS] |= (1 << WP_GAUNTLET); client->ps.ammo[WP_GAUNTLET] = -1; */ // health will count down towards max_health ent->health = client->ps.stats[STAT_HEALTH] = client->ps.stats[STAT_MAX_HEALTH] + 25; client->ps.stats[STAT_ARMOR] = client->ps.stats[STAT_MAX_HEALTH]; G_SetOrigin(ent, spawn_origin); VectorCopy(spawn_origin, client->ps.origin); // the respawned flag will be cleared after the attack and jump keys come up client->ps.pm_flags |= PMF_RESPAWNED; trap_GetUsercmd(client - level.clients, &ent->client->pers.cmd); SetClientViewAngle(ent, spawn_angles); if(ent->client->sess.sessionTeam == TEAM_SPECTATOR) { } else { G_KillBox(ent); trap_LinkEntity(ent); // force the base weapon up //client->ps.weapon = WP_MACHINEGUN; client->ps.weaponstate = WEAPON_READY; } // don't allow full run speed for a bit client->ps.pm_flags |= PMF_TIME_KNOCKBACK; client->ps.pm_time = 100; client->respawnTime = level.time; client->inactivityTime = level.time + g_inactivity.integer * 1000; client->latched_buttons = 0; // set default animations client->ps.torsoAnim = TORSO_STAND; client->ps.legsAnim = LEGS_IDLE; if(level.intermissiontime) { MoveClientToIntermission(ent); } else { // fire the targets of the spawn point G_UseTargets(spawnPoint, ent); #ifdef G_LUA // Lua API callbacks if(spawnPoint && spawnPoint->luaTrigger) { G_LuaHook_EntityTrigger(spawnPoint->luaTrigger, spawnPoint->s.number, ent->s.number); } #endif // select the highest weapon number available, after any // spawn given items have fired client->ps.weapon = 0; for(i = WP_NUM_WEAPONS - 1; i > 0; i--) { if(client->ps.stats[STAT_WEAPONS] & (1 << i)) { client->ps.weapon = i; break; } } } #if defined(ACEBOT) if(ent->r.svFlags & SVF_BOT) { ACESP_SetupBotState(ent); } #endif #ifdef G_LUA // Lua API callbacks G_LuaHook_ClientSpawn(ent->s.number); #endif // run a client frame to drop exactly to the floor, // initialize animations and other things client->ps.commandTime = level.time - 100; ent->client->pers.cmd.serverTime = level.time; ClientThink(ent - g_entities); // positively link the client, even if the command times are weird if(ent->client->sess.sessionTeam != TEAM_SPECTATOR) { BG_PlayerStateToEntityState(&client->ps, &ent->s, qtrue); VectorCopy(ent->client->ps.origin, ent->r.currentOrigin); trap_LinkEntity(ent); } // run the presend to set anything else ClientEndFrame(ent); // clear entity state values BG_PlayerStateToEntityState(&client->ps, &ent->s, qtrue); }