/*QUAKED func_button (0 .5 .8) ? When a button is touched, it moves some distance in the direction of its angle, triggers all of its targets, waits some time, then returns to its original position where it can be triggered again. "model2" .md3 model to also draw "angle" determines the opening direction "target" all entities with a matching targetname will be used "speed" override the default 40 speed "wait" override the default 1 second wait (-1 = never return) "lip" override the default 4 pixel lip remaining at end of move "health" if set, the button must be killed instead of touched "color" constantLight color "light" constantLight radius */ void SP_func_button( gentity_t *ent ) { vector3 abs_movedir; float distance; vector3 size; float lip; ent->sound1to2 = G_SoundIndex("sound/movers/switches/butn2.wav"); if ( !ent->speed ) { ent->speed = 40; } if ( !ent->wait ) { ent->wait = 1; } ent->wait *= 1000; // first position VectorCopy( &ent->s.origin, &ent->pos1 ); // calculate second position trap->SV_SetBrushModel( (sharedEntity_t *)ent, ent->model ); G_SpawnFloat( "lip", "4", &lip ); G_SetMovedir( &ent->s.angles, &ent->movedir ); abs_movedir.x = fabsf(ent->movedir.x); abs_movedir.y = fabsf(ent->movedir.y); abs_movedir.z = fabsf(ent->movedir.z); VectorSubtract( &ent->r.maxs, &ent->r.mins, &size ); distance = abs_movedir.x * size.x + abs_movedir.y * size.y + abs_movedir.z * size.z - lip; VectorMA (&ent->pos1, distance, &ent->movedir, &ent->pos2); if (ent->health) { // shootable button ent->takedamage = qtrue; } else { // touchable button ent->touch = Touch_Button; } InitMover( ent ); }
/*QUAKED func_button (0 .5 .8) ? When a button is touched, it moves some distance in the direction of its angle, triggers all of its targets, waits some time, then returns to its original position where it can be triggered again. "model2" .md3 model to also draw "angle" determines the opening direction "target" all entities with a matching targetname will be used "speed" override the default 40 speed "wait" override the default 1 second wait (-1 = never return) "lip" override the default 4 pixel lip remaining at end of move "health" if set, the button must be killed instead of touched "color" constantLight color "light" constantLight radius */ void SP_func_button( gentity_t *ent ) { vec3_t abs_movedir; float distance; vec3_t size; float lip; ent->sound1to2 = G_SoundIndex("sound/movers/switches/butn2.wav"); if ( !ent->speed ) { ent->speed = 40; } if ( !ent->wait ) { ent->wait = 1; } ent->wait *= 1000; // first position VectorCopy( ent->s.origin, ent->pos1 ); // calculate second position G_SetBrushModel( ent, ent->model ); G_SpawnFloat( "lip", "4", &lip ); G_SetMovedir( ent->s.angles, ent->movedir ); abs_movedir[0] = fabs(ent->movedir[0]); abs_movedir[1] = fabs(ent->movedir[1]); abs_movedir[2] = fabs(ent->movedir[2]); VectorSubtract( ent->s.maxs, ent->s.mins, size ); distance = abs_movedir[0] * size[0] + abs_movedir[1] * size[1] + abs_movedir[2] * size[2] - lip; VectorMA (ent->pos1, distance, ent->movedir, ent->pos2); if (ent->health) { // shootable button ent->takedamage = qtrue; } else { // touchable button ent->touch = Touch_Button; } InitMover( ent ); }
void InitShooter( gentity_t *ent, int weapon ) { ent->use = Use_Shooter; ent->s.weapon = weapon; RegisterItem( BG_FindItemForWeapon( weapon ) ); G_SetMovedir( &ent->s.angles, &ent->movedir ); if ( !ent->random ) { ent->random = 1.0; } ent->random = sinf( M_PI * ent->random / 180 ); // target might be a moving object, so we can't set movedir for it if ( ent->target ) { ent->think = InitShooter_Finish; ent->nextthink = level.time + 500; } trap->SV_LinkEntity( (sharedEntity_t *)ent ); }
virtual void execute() { vec3_t dir; GameEntity* target; GameEntity* owner; owner = G_PickTarget( self_->target_ ); if ( !owner ) { Com_Printf( "Couldn't find target for misc_partal_surface\n" ); self_->freeUp(); return; } self_->r.ownerNum = owner->s.number; // frame holds the rotate speed if ( owner->spawnflags_ & 1 ) self_->s.frame = 25; else if ( owner->spawnflags_ & 2 ) self_->s.frame = 75; // set to 0 for no rotation at all self_->s.objectives = 1; // clientNum holds the rotate offset self_->s.clientNum = owner->s.clientNum; VectorCopy( owner->s.origin, self_->s.origin2 ); // see if the portal_camera has a target target = G_PickTarget( owner->target_ ); if ( target ) { VectorSubtract( target->s.origin, owner->s.origin, dir ); VectorNormalize( dir ); } else { G_SetMovedir( owner->s.angles, dir ); } self_->s.eventParm = DirToByte( dir ); }
/*QUAKED target_push (.5 .5 .5) (-8 -8 -8) (8 8 8) bouncepad Pushes the activator in the direction.of angle, or towards a target apex. "speed" defaults to 1000 if "bouncepad", play bounce noise instead of windfly */ void SP_target_push( gentity_t *self ) { if (!self->speed) { self->speed = 1000; } G_SetMovedir (self->s.angles, self->s.origin2); VectorScale (self->s.origin2, self->speed, self->s.origin2); if ( self->spawnflags & 1 ) { self->noise_index = G_SoundIndex("sounds/world/jumppad"); } if ( self->target ) { VectorCopy( self->s.origin, self->r.absmin ); VectorCopy( self->s.origin, self->r.absmax ); self->think = AimAtTarget; self->nextthink = level.time + FRAMETIME; } self->use = Use_target_push; }
void InitTrigger(gentity_t *self) { if (!VectorCompare(self->s.angles, vec3_origin)) { G_SetMovedir(self->s.angles, self->movedir); } if (self->model) { trap_SetBrushModel(self, self->model); } else { // empty models for ETPro mapscripting G_DPrintf("^6InitTrigger: trap_SetBrushModel(NULL) skipped for scriptName %s\n", self->scriptName); } self->r.contents = CONTENTS_TRIGGER; // replaces the -1 from trap_SetBrushModel self->r.svFlags = SVF_NOCLIENT; }
/*QUAKED target_push (.5 .5 .5) (-8 -8 -8) (8 8 8) Pushes the activator in the direction.of angle, or towards a target apex. "speed" defaults to 1000 */ void SP_target_push( gentity_t *self ) { if ( !self->speed ) { self->speed = 1000; } G_SetMovedir( self->s.angles, self->s.origin2 ); VectorScale( self->s.origin2, self->speed, self->s.origin2 ); if ( self->target ) { VectorCopy( self->s.origin, self->r.absmin ); VectorCopy( self->s.origin, self->r.absmax ); self->think = AimAtTarget; self->nextthink = level.time + FRAMETIME; } self->use = Use_target_push; }
/*QUAKED target_push (.5 .5 .5) (-8 -8 -8) (8 8 8) bouncepad CONSTANT CONSTANT will push activator in direction of 'target' at constant 'speed' Pushes the activator in the direction.of angle, or towards a target apex. "speed" defaults to 1000 if "bouncepad", play bounce noise instead of none */ void SP_target_push( gentity_t *self ) { if (!self->speed) { self->speed = 1000; } G_SetMovedir (self->s.angles, self->s.origin2); VectorScale (self->s.origin2, self->speed, self->s.origin2); if ( self->spawnflags & 1 ) { self->noise_index = G_SoundIndex("sound/weapons/force/jump.wav"); } else { self->noise_index = 0; //G_SoundIndex("sound/misc/windfly.wav"); } if ( self->target ) { VectorCopy( self->s.origin, self->r.absmin ); VectorCopy( self->s.origin, self->r.absmax ); self->think = AimAtTarget; self->nextthink = level.time + FRAMETIME; } self->use = Use_target_push; }
void locateCamera(gentity_t *ent) { vec3_t dir; gentity_t *target; gentity_t *owner; owner = G_PickTarget(ent->target); if (!owner) { G_Printf("Couldn't find target for misc_portal_surface\n"); G_FreeEntity(ent); return; } ent->r.ownerNum = owner->s.number; // frame holds the rotate speed if (owner->spawnflags & 1) ent->s.frame = 25; else if (owner->spawnflags & 2) ent->s.frame = 75; // swing camera ? if (owner->spawnflags & 4) { // set to 0 for no rotation at all ent->s.powerups = 0; } else ent->s.powerups = 1; // clientNum holds the rotate offset ent->s.clientNum = owner->s.clientNum; VectorCopy(owner->s.origin, ent->s.origin2); // see if the portal_camera has a target target = G_PickTarget(owner->target); if (target) { VectorSubtract(target->s.origin, owner->s.origin, dir); VectorNormalize(dir); } else G_SetMovedir(owner->s.angles, dir); ent->s.eventParm = DirToByte(dir); }
static void trigger_push_setup( edict_t *self ) { vec3_t origin, velocity; float height, time; float dist; edict_t *target; if( !self->target ) { vec3_t movedir; G_SetMovedir( self->s.angles, movedir ); VectorScale( movedir, (self->speed ? self->speed : 1000) * 10, self->s.origin2 ); return; } target = G_PickTarget( self->target ); if( !target ) { G_FreeEdict( self ); return; } VectorAdd( self->r.absmin, self->r.absmax, origin ); VectorScale( origin, 0.5, origin ); height = target->s.origin[2] - origin[2]; time = sqrt( height / ( 0.5 * g_gravity->value ) ); if( !time ) { G_FreeEdict( self ); return; } VectorSubtract( target->s.origin, origin, velocity ); velocity[2] = 0; dist = VectorNormalize( velocity ); VectorScale( velocity, dist / time, velocity ); velocity[2] = time * g_gravity->value; VectorCopy( velocity, self->s.origin2 ); }
/*QUAKED target_push (.5 .5 .5) (-8 -8 -8) (8 8 8) ENERGYNOISE CONSTANT NO_DAMAGE When triggered, pushes the activator in the direction of angles "speed" defaults to 1000 ENERGYNOISE plays energy noise CONSTANT will push activator in direction of 'target' at constant 'speed' NO_DAMAGE the activator won't take falling damage after being pushed */ void SP_target_push( gentity_t *self ) { if (!self->speed) { self->speed = 1000; } G_SetMovedir (self->s.angles, self->s.origin2); VectorScale (self->s.origin2, self->speed, self->s.origin2); if ( self->spawnflags & 1 ) { //self->noise_index = G_SoundIndex("sound/ambience/forge/antigrav.wav"); } if ( self->target ) { VectorCopy( self->s.origin, self->absmin ); VectorCopy( self->s.origin, self->absmax ); self->e_ThinkFunc = thinkF_AimAtTarget; self->nextthink = level.time + START_TIME_LINK_ENTS; } self->e_UseFunc = useF_Use_target_push; }
void InitShooter( gentity_t *ent, int weapon ) { ent->use = Use_Shooter; ent->s.weapon = weapon; #ifdef SMOKINGUNS if(weapon != WP_NONE) #endif RegisterItem( BG_FindItemForWeapon( weapon ) ); G_SetMovedir( ent->s.angles, ent->movedir ); if ( !ent->random ) { ent->random = 1.0; } ent->random = sin( M_PI * ent->random / 180 ); // target might be a moving object, so we can't set movedir for it if ( ent->target ) { ent->think = InitShooter_Finish; ent->nextthink = level.time + 500; } trap_LinkEntity( ent ); }
void target_laser_start(gentity_t *self) { gentity_t *ent; self->s.eType = ET_BEAM; if(self->target) { ent = G_Find(NULL, FOFS(targetname), self->target); if(!ent) { G_Printf("%s at %s: %s is a bad target\n", self->classname, vtos(self->s.origin), self->target); } self->enemy = ent; } else { G_SetMovedir(self->s.angles, self->movedir); } self->use = target_laser_use; self->think = target_laser_think; if(!self->damage) { self->damage = 1; } if(self->spawnflags & 1) { target_laser_on(self); } else { target_laser_off(self); } }
/* * QUAKED dm_dball_goal (1 .5 .5) ? TEAM1 TEAM2 * Deathball goal * * Team1/Team2 - beneficiary of this goal. when the ball enters this goal, the beneficiary team will score. * * "wait": score to be given for this goal (default 10) player gets score+5. */ void SP_dm_dball_goal(edict_t *self) { if (!self) { return; } if (!(deathmatch->value)) { G_FreeEdict(self); return; } if (gamerules && (gamerules->value != RDM_DEATHBALL)) { G_FreeEdict(self); return; } if (!self->wait) { self->wait = 10; } self->touch = DBall_GoalTouch; self->solid = SOLID_TRIGGER; self->movetype = MOVETYPE_NONE; self->svflags |= SVF_NOCLIENT; if (!VectorCompare(self->s.angles, vec3_origin)) { G_SetMovedir(self->s.angles, self->movedir); } gi.setmodel(self, self->model); gi.linkentity(self); }
void SP_target_blaster (edict_t *self) { if (!self) { return; } self->use = use_target_blaster; G_SetMovedir(self->s.angles, self->movedir); self->noise_index = gi.soundindex("weapons/laser2.wav"); if (!self->dmg) { self->dmg = 15; } if (!self->speed) { self->speed = 1000; } self->svflags = SVF_NOCLIENT; }
/*QUAKED func_door (0 .5 .8) ? START_OPEN x CRUSHER TOGGLE wait in both the start and end states for a trigger event. START_OPEN the door to moves to its destination when spawned, and operate in reverse. It is used to temporarily or permanently close off an area when triggered (not useful for touch or takedamage doors). NOMONSTER monsters will not trigger this door "model2" .md3 model to also draw "angle" determines the opening direction "targetname" if set, no touch field will be spawned and a remote button or trigger field activates the door. "speed" movement speed (100 default) "wait" wait before returning (3 default, -1 = never return) "lip" lip remaining at end of move (8 default) "dmg" damage to inflict when blocked (2 default) "color" constantLight color "light" constantLight radius "health" if set, the door must be shot open */ void SP_func_door (gentity_t *ent) { vec3_t abs_movedir; float distance; vec3_t size; float lip; ent->sound1to2 = ent->sound2to1 = G_SoundIndex("sound/movers/doors/dr1_strt.wav"); ent->soundPos1 = ent->soundPos2 = G_SoundIndex("sound/movers/doors/dr1_end.wav"); ent->blocked = Blocked_Door; // default speed of 400 if (!ent->speed) ent->speed = 400; // default wait of 2 seconds if (!ent->wait) ent->wait = 2; ent->wait *= 1000; // default lip of 8 units G_SpawnFloat( "lip", "8", &lip ); // default damage of 2 points G_SpawnInt( "dmg", "2", &ent->damage ); // first position at start VectorCopy( ent->s.origin, ent->pos1 ); // calculate second position trap_SetBrushModel( ent, ent->model ); G_SetMovedir (ent->s.angles, ent->movedir); abs_movedir[0] = fabs(ent->movedir[0]); abs_movedir[1] = fabs(ent->movedir[1]); abs_movedir[2] = fabs(ent->movedir[2]); VectorSubtract( ent->r.maxs, ent->r.mins, size ); distance = DotProduct( abs_movedir, size ) - lip; VectorMA( ent->pos1, distance, ent->movedir, ent->pos2 ); // if "start_open", reverse position 1 and 2 if ( ent->spawnflags & 1 ) { vec3_t temp; VectorCopy( ent->pos2, temp ); VectorCopy( ent->s.origin, ent->pos2 ); VectorCopy( temp, ent->pos1 ); } InitMover( ent ); ent->nextthink = level.time + FRAMETIME; if ( ! (ent->flags & FL_TEAMSLAVE ) ) { int health; G_SpawnInt( "health", "0", &health ); if ( health ) { ent->takedamage = qtrue; } if ( ent->targetname || health ) { // non touch/shoot doors ent->think = Think_MatchTeam; } else { ent->think = Think_SpawnNewDoorTrigger; } } }
void SP_target_mal_laser(edict_t *self) { if (!self) { return; } self->movetype = MOVETYPE_NONE; self->solid = SOLID_NOT; self->s.renderfx |= RF_BEAM | RF_TRANSLUCENT; self->s.modelindex = 1; /* must be non-zero */ /* set the beam diameter */ if (self->spawnflags & 64) { self->s.frame = 16; } else { self->s.frame = 4; } /* set the color */ if (self->spawnflags & 2) { self->s.skinnum = 0xf2f2f0f0; } else if (self->spawnflags & 4) { self->s.skinnum = 0xd0d1d2d3; } else if (self->spawnflags & 8) { self->s.skinnum = 0xf3f3f1f1; } else if (self->spawnflags & 16) { self->s.skinnum = 0xdcdddedf; } else if (self->spawnflags & 32) { self->s.skinnum = 0xe0e1e2e3; } G_SetMovedir(self->s.angles, self->movedir); if (!self->delay) { self->delay = 0.1; } if (!self->wait) { self->wait = 0.1; } if (!self->dmg) { self->dmg = 5; } VectorSet(self->mins, -8, -8, -8); VectorSet(self->maxs, 8, 8, 8); self->nextthink = level.time + self->delay; self->think = mal_laser_think; self->use = target_mal_laser_use; gi.linkentity(self); if (self->spawnflags & 1) { target_mal_laser_on(self); } else { target_mal_laser_off(self); } }
void SP_func_water (edict_t *self) { vec3_t abs_movedir; G_SetMovedir (self->s.angles, self->movedir); self->movetype = MOVETYPE_PUSH; self->solid = SOLID_BSP; gi.setmodel (self, self->model); switch (self->sounds) { default: break; case 1: // water self->moveinfo.sound_start = gi.soundindex ("world/mov_watr.wav"); self->moveinfo.sound_end = gi.soundindex ("world/stp_watr.wav"); break; case 2: // lava self->moveinfo.sound_start = gi.soundindex ("world/mov_watr.wav"); self->moveinfo.sound_end = gi.soundindex ("world/stp_watr.wav"); break; } // calculate second position VectorCopy (self->s.origin, self->pos1); abs_movedir[0] = fabs(self->movedir[0]); abs_movedir[1] = fabs(self->movedir[1]); abs_movedir[2] = fabs(self->movedir[2]); self->moveinfo.distance = abs_movedir[0] * self->size[0] + abs_movedir[1] * self->size[1] + abs_movedir[2] * self->size[2] - st.lip; VectorMA (self->pos1, self->moveinfo.distance, self->movedir, self->pos2); // if it starts open, switch the positions if (self->spawnflags & DOOR_START_OPEN) { VectorCopy (self->pos2, self->s.origin); VectorCopy (self->pos1, self->pos2); VectorCopy (self->s.origin, self->pos1); } VectorCopy (self->pos1, self->moveinfo.start_origin); VectorCopy (self->s.angles, self->moveinfo.start_angles); VectorCopy (self->pos2, self->moveinfo.end_origin); VectorCopy (self->s.angles, self->moveinfo.end_angles); self->moveinfo.state = STATE_BOTTOM; if (!self->speed) self->speed = 25; self->moveinfo.accel = self->moveinfo.decel = self->moveinfo.speed = self->speed; if (!self->wait) self->wait = -1; self->moveinfo.wait = self->wait; self->use = door_use; if (self->wait == -1) self->spawnflags |= DOOR_TOGGLE; self->classname = "func_door"; gi.linkentity (self); }
void SP_func_door (edict_t *ent) { vec3_t abs_movedir; if (ent->sounds != 1) { ent->moveinfo.sound_start = gi.soundindex ("doors/dr1_strt.wav"); ent->moveinfo.sound_middle = gi.soundindex ("doors/dr1_mid.wav"); ent->moveinfo.sound_end = gi.soundindex ("doors/dr1_end.wav"); } G_SetMovedir (ent->s.angles, ent->movedir); ent->movetype = MOVETYPE_PUSH; ent->solid = SOLID_BSP; gi.setmodel (ent, ent->model); ent->blocked = door_blocked; ent->use = door_use; if (!ent->speed) ent->speed = 100; if (deathmatch->value) ent->speed *= 2; if (!ent->accel) ent->accel = ent->speed; if (!ent->decel) ent->decel = ent->speed; if (!ent->wait) ent->wait = 3; if (!st.lip) st.lip = 8; if (!ent->dmg) ent->dmg = 2; // calculate second position VectorCopy (ent->s.origin, ent->pos1); abs_movedir[0] = fabs(ent->movedir[0]); abs_movedir[1] = fabs(ent->movedir[1]); abs_movedir[2] = fabs(ent->movedir[2]); ent->moveinfo.distance = abs_movedir[0] * ent->size[0] + abs_movedir[1] * ent->size[1] + abs_movedir[2] * ent->size[2] - st.lip; VectorMA (ent->pos1, ent->moveinfo.distance, ent->movedir, ent->pos2); // if it starts open, switch the positions if (ent->spawnflags & DOOR_START_OPEN) { VectorCopy (ent->pos2, ent->s.origin); VectorCopy (ent->pos1, ent->pos2); VectorCopy (ent->s.origin, ent->pos1); } ent->moveinfo.state = STATE_BOTTOM; if (ent->health) { ent->takedamage = DAMAGE_YES; ent->die = door_killed; ent->max_health = ent->health; } else if (ent->targetname && ent->message) { gi.soundindex ("misc/talk.wav"); ent->touch = door_touch; } ent->moveinfo.speed = ent->speed; ent->moveinfo.accel = ent->accel; ent->moveinfo.decel = ent->decel; ent->moveinfo.wait = ent->wait; VectorCopy (ent->pos1, ent->moveinfo.start_origin); VectorCopy (ent->s.angles, ent->moveinfo.start_angles); VectorCopy (ent->pos2, ent->moveinfo.end_origin); VectorCopy (ent->s.angles, ent->moveinfo.end_angles); if (ent->spawnflags & 16) ent->s.effects |= EF_ANIM_ALL; if (ent->spawnflags & 64) ent->s.effects |= EF_ANIM_ALLFAST; // to simplify logic elsewhere, make non-teamed doors into a team of one if (!ent->team) ent->teammaster = ent; gi.linkentity (ent); ent->nextthink = level.time + FRAMETIME; if (ent->health || ent->targetname) ent->think = Think_CalcMoveSpeed; else ent->think = Think_SpawnDoorTrigger; }
void TeleportPlayer( gentity_t *player, vec3_t origin, vec3_t angles ) { gentity_t *tent; // use temp events at source and destination to prevent the effect // from getting dropped by a second player event #ifndef SMOKINGUNS if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) { #else if ( player->client->sess.sessionTeam < TEAM_SPECTATOR ) { #endif tent = G_TempEntity( player->client->ps.origin, EV_PLAYER_TELEPORT_OUT ); tent->s.clientNum = player->s.clientNum; tent = G_TempEntity( origin, EV_PLAYER_TELEPORT_IN ); tent->s.clientNum = player->s.clientNum; } // unlink to make sure it can't possibly interfere with G_KillBox trap_UnlinkEntity (player); VectorCopy ( origin, player->client->ps.origin ); player->client->ps.origin[2] += 1; // spit the player out AngleVectors( angles, player->client->ps.velocity, NULL, NULL ); VectorScale( player->client->ps.velocity, 400, player->client->ps.velocity ); player->client->ps.pm_time = 160; // hold time player->client->ps.pm_flags |= PMF_TIME_KNOCKBACK; // toggle the teleport bit so the client knows to not lerp player->client->ps.eFlags ^= EF_TELEPORT_BIT; #ifdef SMOKINGUNS //unlagged - backward reconciliation #3 // we don't want players being backward-reconciled back through teleporters G_ResetHistory( player ); //unlagged - backward reconciliation #3 #endif // set angles SetClientViewAngle( player, angles ); // kill anything at the destination #ifndef SMOKINGUNS if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) { #else if ( player->client->sess.sessionTeam < TEAM_SPECTATOR ) { #endif G_KillBox (player); #ifdef SMOKINGUNS // Tequila comment: G_KillBox will set dontTelefrag as needed if (player->client->dontTelefrag) { #ifdef DEBUG_TELEFRAG_CASE G_Printf(S_COLOR_MAGENTA "TeleportPlayer: Telefrag case delayed at respawn for %s...\n",player->client->pers.netname); #endif trap_SendServerCommand( player->s.clientNum, va("print \"Go away %s\n\"",player->client->pers.netname) ); // So we will link the player entity later with normal content player->r.contents = 0; } #endif } // save results of pmove BG_PlayerStateToEntityState( &player->client->ps, &player->s, qtrue ); // use the precise origin for linking VectorCopy( player->client->ps.origin, player->r.currentOrigin ); #ifndef SMOKINGUNS if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) { #else if ( player->client->sess.sessionTeam < TEAM_SPECTATOR ) { #endif trap_LinkEntity (player); } } /*QUAKED misc_teleporter_dest (1 0 0) (-32 -32 -24) (32 32 -16) Point teleporters at these. Now that we don't have teleport destination pads, this is just an info_notnull */ void SP_misc_teleporter_dest( gentity_t *ent ) { } #ifdef SMOKINGUNS // Imported from WoP OpenSource project //=========================================================== /*QUAKED misc_externalmodel (1 0 0) (-16 -16 -16) (16 16 16) "model" arbitrary .md3 file to display "wait" time in seconds before the animation begins */ #define ANIMATION_THINKTIME 50 static void Think_AnimationExternalmodel( gentity_t *ent ) { if(ent->animationEnd>ent->animationStart) { ent->s.frame = (int)((float)level.time*0.001f*ent->animationFPS)%(ent->animationEnd-ent->animationStart); ent->s.frame += ent->animationStart; ent->nextthink = level.time + ANIMATION_THINKTIME; } } void SP_misc_externalmodel( gentity_t *ent ) { ent->s.modelindex = G_ModelIndex( ent->model ); // VectorSet (ent->mins, -16, -16, -16); // VectorSet (ent->maxs, 16, 16, 16); trap_LinkEntity (ent); G_SetOrigin( ent, ent->s.origin ); VectorCopy( ent->s.angles, ent->s.apos.trBase ); if(ent->animationEnd>ent->animationStart && ent->animationFPS>0.0f) { ent->think = Think_AnimationExternalmodel; ent->nextthink = level.time + ANIMATION_THINKTIME; // Tequila: Support for new entity features if (ent->wait>0.0f) ent->nextthink += (int)(ent->wait*1000); } } #endif //=========================================================== /*QUAKED misc_model (1 0 0) (-16 -16 -16) (16 16 16) "model" arbitrary .md3 file to display */ void SP_misc_model( gentity_t *ent ) { #if 0 ent->s.modelindex = G_ModelIndex( ent->model ); VectorSet (ent->mins, -16, -16, -16); VectorSet (ent->maxs, 16, 16, 16); trap_LinkEntity (ent); G_SetOrigin( ent, ent->s.origin ); VectorCopy( ent->s.angles, ent->s.apos.trBase ); #else G_FreeEntity( ent ); #endif } //=========================================================== void locateCamera( gentity_t *ent ) { vec3_t dir; gentity_t *target; gentity_t *owner; owner = G_PickTarget( ent->target ); if ( !owner ) { G_Printf( "Couldn't find target for misc_portal_surface\n" ); G_FreeEntity( ent ); return; } ent->r.ownerNum = owner->s.number; // frame holds the rotate speed if ( owner->spawnflags & 1 ) { ent->s.frame = 25; } else if ( owner->spawnflags & 2 ) { ent->s.frame = 75; } #ifndef SMOKINGUNS // swing camera ? if ( owner->spawnflags & 4 ) { // set to 0 for no rotation at all ent->s.powerups = 0; } else { ent->s.powerups = 1; } #else // set to 0 for no rotation at all ent->s.powerups = 1; #endif // clientNum holds the rotate offset ent->s.clientNum = owner->s.clientNum; VectorCopy( owner->s.origin, ent->s.origin2 ); // see if the portal_camera has a target target = G_PickTarget( owner->target ); if ( target ) { VectorSubtract( target->s.origin, owner->s.origin, dir ); VectorNormalize( dir ); } else { G_SetMovedir( owner->s.angles, dir ); } ent->s.eventParm = DirToByte( dir ); }
void target_laser_start (edict_t *self) { edict_t *ent; if (!self) { return; } self->movetype = MOVETYPE_NONE; self->solid = SOLID_NOT; self->s.renderfx |= RF_BEAM|RF_TRANSLUCENT; self->s.modelindex = 1; // must be non-zero // set the beam diameter if (self->spawnflags & 64) self->s.frame = 16; else self->s.frame = 4; // set the color if (self->spawnflags & 2) self->s.skinnum = 0xf2f2f0f0; else if (self->spawnflags & 4) self->s.skinnum = 0xd0d1d2d3; else if (self->spawnflags & 8) self->s.skinnum = 0xf3f3f1f1; else if (self->spawnflags & 16) self->s.skinnum = 0xdcdddedf; else if (self->spawnflags & 32) self->s.skinnum = 0xe0e1e2e3; if (!self->enemy) { if (self->target) { ent = G_Find (NULL, FOFS(targetname), self->target); if (!ent) gi.dprintf ("%s at %s: %s is a bad target\n", self->classname, vtos(self->s.origin), self->target); self->enemy = ent; } else { G_SetMovedir (self->s.angles, self->movedir); } } self->use = target_laser_use; self->think = target_laser_think; if (!self->dmg) self->dmg = 1; Vector3Set (self->mins, -8, -8, -8); Vector3Set (self->maxs, 8, 8, 8); gi.linkentity (self); if (self->spawnflags & 1) target_laser_on (self); else target_laser_off (self); }
void PlaceLaser (edict_t *ent) { edict_t *laser, *grenade; edict_t *blip = NULL;//GHz vec3_t forward, wallp, start, end; trace_t tr; trace_t endTrace; int health=0; if (debuginfo->value) gi.dprintf("DEBUG: %s just called PlaceLaser()\n", ent->client->pers.netname); health = LASER_INITIAL_HEALTH+LASER_ADDON_HEALTH*ent->myskills.abilities[BUILD_LASER].current_level; // valid ent ? if ((!ent->client) || (ent->health<=0)) return; if ((deathmatch->value) && (level.time < pregame_time->value)) { if (ent->client) safe_cprintf(ent, PRINT_HIGH, "You cannot use this ability in pre-game!\n"); return; } if (Q_strcasecmp (gi.args(), "remove") == 0) { RemoveLaserDefense(ent); return; } if(ent->myskills.abilities[BUILD_LASER].disable) return; //3.0 amnesia disables lasers if (que_findtype(ent->curses, NULL, AMNESIA) != NULL) return; if (ent->myskills.abilities[BUILD_LASER].current_level < 1) { safe_cprintf(ent, PRINT_HIGH, "You can't make lasers due to not training in it!\n"); return; } // cells for laser ? if (ent->client->pers.inventory[power_cube_index] < LASER_COST) { safe_cprintf(ent, PRINT_HIGH, "Not enough Power Cubes for laser.\n"); return; } if (ent->client->ability_delay > level.time) { safe_cprintf (ent, PRINT_HIGH, "You can't use abilities for another %2.1f seconds\n", ent->client->ability_delay - level.time); return; } ent->client->ability_delay = level.time + DELAY_LASER; //gi.dprintf("DEBUG: %s is attempting to place a laser...\n", ent->client->pers.netname); // GHz: Reached max number allowed ? if (ent->num_lasers >= MAX_LASERS) { safe_cprintf(ent, PRINT_HIGH, "You have reached the max of %d lasers\n", MAX_LASERS); return; } // Setup "little look" to close wall VectorCopy(ent->s.origin,wallp); // Cast along view angle AngleVectors (ent->client->v_angle, forward, NULL, NULL); // Setup end point wallp[0]=ent->s.origin[0]+forward[0]*128; wallp[1]=ent->s.origin[1]+forward[1]*128; wallp[2]=ent->s.origin[2]+forward[2]*128; // trace tr = gi.trace (ent->s.origin, NULL, NULL, wallp, ent, MASK_SOLID); // Line complete ? (ie. no collision) if (tr.fraction == 1.0) { safe_cprintf (ent, PRINT_HIGH, "Too far from wall.\n"); return; } // Hit sky ? if (tr.surface) if (tr.surface->flags & SURF_SKY) return; /* while (blip = findradius (blip, ent->s.origin, 64)) { if (!visible(ent, blip)) continue; if ( (!strcmp(blip->classname, "worldspawn") ) || (!strcmp(blip->classname, "info_player_start") ) || (!strcmp(blip->classname, "info_player_deathmatch") ) || (!strcmp(blip->classname, "item_flagreturn_team1") ) || (!strcmp(blip->classname, "item_flagreturn_team2") ) || (!strcmp(blip->classname, "misc_teleporter_dest") ) || (!strcmp(blip->classname, "info_teleport_destination") ) ) { safe_cprintf (ent, PRINT_HIGH, "Laser is too close to a spawnpoint or flag.\n"); return ; } } */ // Ok, lets stick one on then ... safe_cprintf (ent, PRINT_HIGH, "Laser attached.\n"); /* if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) { ent->client->pers.inventory[power_cube_index] -= LASER_COST; ent->client->pers.inventory[ITEM_INDEX(FindItem("Lasers"))]--; }*/ // get entities for both objects grenade = G_Spawn(); laser = G_Spawn(); // setup the Grenade VectorClear (grenade->mins); VectorClear (grenade->maxs); VectorCopy (tr.endpos, grenade->s.origin); vectoangles(tr.plane.normal, grenade->s.angles); grenade -> movetype = MOVETYPE_NONE; grenade -> clipmask = MASK_SHOT; grenade->solid = SOLID_BBOX; VectorSet(grenade->mins, -3, -3, 0); VectorSet(grenade->maxs, 3, 3, 6); grenade -> takedamage = DAMAGE_NO; grenade -> s.modelindex = gi.modelindex ("models/objects/grenade2/tris.md2"); grenade -> owner = ent; grenade -> creator = laser; grenade -> monsterinfo.aiflags = AI_NOSTEP; grenade -> classname = "laser_defense_gr"; grenade -> nextthink = level.time + LASER_TIMEUP+GetRandom(0,30);//GetRandom((LASER_TIMEUP/2),(2*LASER_TIMEUP)); grenade -> think = laser_cleanup; // Now lets find the other end of the laser // by starting at the grenade position VectorCopy (grenade->s.origin, start); // setup laser movedir (projection of laser) G_SetMovedir (grenade->s.angles, laser->movedir); gi.linkentity (grenade); VectorMA (start, 2048, laser->movedir, end); endTrace = gi.trace (start, NULL, NULL, end, ent, MASK_SOLID); // ----------- // Setup laser // ----------- laser->movetype = MOVETYPE_NONE; laser->solid = SOLID_NOT; laser->s.renderfx = RF_BEAM|RF_TRANSLUCENT; laser->s.modelindex = 1; // must be non-zero laser->s.sound = gi.soundindex ("world/laser.wav"); laser->classname = "laser_defense"; laser->s.frame = 2 /* ent->myskills.build_lasers*/; // as it gets higher in levels, the bigger it gets. beam diameter laser->owner = laser; laser->s.skinnum = laser_colour[LASER_DEFENSE_COLOR]; laser->dmg = LASER_INITIAL_DMG+LASER_ADDON_DMG*ent->myskills.abilities[BUILD_LASER].current_level; laser->think = pre_target_laser_def_think; //laser->delay = level.time + LASER_TIMEUP; laser->health = health; laser->creator = grenade; laser->activator = ent; // start off ... target_laser_off (laser); VectorCopy (endTrace.endpos, laser->s.old_origin); // ... but make automatically come on laser -> nextthink = level.time + 2; // Set orgin of laser to point of contact with wall VectorCopy(endTrace.endpos,laser->s.origin); /* while (blip = findradius (blip, laser->s.origin, 64)) { if (!visible(laser, blip)) continue; if ( (!strcmp(blip->classname, "worldspawn") ) || (!strcmp(blip->classname, "info_player_start") ) || (!strcmp(blip->classname, "info_player_deathmatch") ) || (!strcmp(blip->classname, "item_flagreturn_team1") ) || (!strcmp(blip->classname, "item_flagreturn_team2") ) || (!strcmp(blip->classname, "misc_teleporter_dest") ) || (!strcmp(blip->classname, "info_teleport_destination") ) ) { safe_cprintf (ent, PRINT_HIGH, "Laser is too close to a spawnpoint or flag.\nLaser Removed.\n"); G_FreeEdict(laser); G_FreeEdict(grenade); return ; } } */ // convert normal at point of contact to laser angles vectoangles(tr.plane.normal,laser->s.angles); // setup laser movedir (projection of laser) G_SetMovedir (laser->s.angles, laser->movedir); VectorSet (laser->mins, -18, -18, -18); VectorSet (laser->maxs, 18, 18, 18); // link to world gi.linkentity (laser); ent->num_lasers++; // GHz: add to laser counter //If you use this spell, you uncloak! ent->svflags &= ~SVF_NOCLIENT; ent->client->cloaking = false; ent->client->cloakable = 0; ent->client->pers.inventory[power_cube_index] -= LASER_COST; //gi.dprintf("DEBUG: %s successfully created a laser.\n", ent->client->pers.netname); }