Skip to content

Commit

Permalink
game: sync target_camera with ReRelease
Browse files Browse the repository at this point in the history
  • Loading branch information
0lvin committed Dec 27, 2024
1 parent 05b2b39 commit fd4a7ab
Show file tree
Hide file tree
Showing 6 changed files with 226 additions and 10 deletions.
2 changes: 1 addition & 1 deletion src/common/cmodels.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ Mod_DecompressVis(const byte *in, byte *out, const byte* numvisibility, int row)
{
int c;

if (*in && (in + 2) < numvisibility)
if (((in + 2) < numvisibility) && *in)
{
*out_p++ = *in++;
continue;
Expand Down
220 changes: 213 additions & 7 deletions src/game/g_target.c
Original file line number Diff line number Diff line change
Expand Up @@ -1474,12 +1474,161 @@ SP_target_earthquake(edict_t *self)

/*
* QUAKED target_camera (1 0 0) (-8 -8 -8) (8 8 8)
* [Sam-KEX] Creates a camera path as seen in the N64 version.
*
* Creates a camera path as seen in the N64 version.
*/
static void
camera_lookat_pathtarget(edict_t* self, vec3_t origin, vec3_t* dest)
{
if(self->pathtarget)
{
edict_t* pt = NULL;

pt = G_Find(pt, FOFS(targetname), self->pathtarget);
if (pt)
{
float yaw, pitch, d;
vec3_t delta;

VectorSubtract(pt->s.origin, origin, delta);

d = delta[0] * delta[0] + delta[1] * delta[1];
if(d == 0.0f)
{
yaw = 0.0f;
pitch = (delta[2] > 0.0f) ? 90.0f : -90.0f;
}
else
{
yaw = atan2(delta[1], delta[0]) * (180.0f / M_PI);
pitch = atan2(delta[2], sqrt(d)) * (180.0f / M_PI);
}

(*dest)[YAW] = yaw;
(*dest)[PITCH] = -pitch;
(*dest)[ROLL] = 0;
}
}
}

void
update_target_camera_think(edict_t *self)
{
if (self->movetarget)
{
self->moveinfo.remaining_distance -= (self->moveinfo.move_speed * FRAMETIME) * 0.8f;

if(self->moveinfo.remaining_distance <= 0)
{
VectorCopy(self->movetarget->s.origin, self->s.origin);
self->nextthink = level.time + self->movetarget->wait;
if (self->movetarget->target)
{
self->movetarget = G_PickTarget(self->movetarget->target);

if (self->movetarget)
{
vec3_t diff;

self->moveinfo.move_speed = self->movetarget->speed ? self->movetarget->speed : 55;
VectorSubtract(self->movetarget->s.origin, self->s.origin, diff);
self->moveinfo.remaining_distance = VectorNormalize(diff);
self->moveinfo.distance = self->moveinfo.remaining_distance;
}
}
else
{
self->movetarget = NULL;
}

return;
}
else
{
vec3_t delta, newpos;
float frac;
int i;

frac = 1.0f - (self->moveinfo.remaining_distance / self->moveinfo.distance);

VectorSubtract(self->movetarget->s.origin, self->s.origin, delta);
VectorScale(delta, frac, delta);

VectorAdd(self->s.origin, delta, newpos);

camera_lookat_pathtarget(self, newpos, &level.intermission_angle);
VectorCopy(newpos, level.intermission_origin);

/* move all clients to the intermission point */
for (i = 0; i < game.maxclients; i++)
{
edict_t *client = g_edicts + 1 + i;

if (!client->inuse)
{
continue;
}

MoveClientToIntermission(client);
}
}
}
else
{
if (self->killtarget)
{
edict_t *t = NULL;

/* destroy dummy player */
if (self->enemy)
{
G_FreeEdict(self->enemy);
}

level.intermissiontime = 0;

while ((t = G_Find(t, FOFS(targetname), self->killtarget)))
{
t->use(t, self, self->activator);
}

level.intermissiontime = level.time;

/* end of unit requires a wait */
if (level.changemap && !strchr(level.changemap, '*'))
{
level.exitintermission = true;
}
}

self->think = NULL;
return;
}

self->nextthink = level.time + FRAMETIME;
}

void
target_camera_dummy_think(edict_t *self)
{
/*
* bit of a hack, but this will let the dummy
* move like a player
*/
self->client = self->owner->client;
G_SetClientFrame(self, sqrtf(
self->velocity[0] * self->velocity[0] +
self->velocity[1] * self->velocity[1]));
self->client = NULL;

self->nextthink = level.time + FRAMETIME;
}

void
use_target_camera(edict_t *self, edict_t *other, edict_t *activator)
{
edict_t *target;
vec3_t diff;
int i;

if (!self)
{
Expand All @@ -1491,20 +1640,77 @@ use_target_camera(edict_t *self, edict_t *other, edict_t *activator)
gi.configstring(CS_CDTRACK, va("%i", self->sounds));
}

if (!self->killtarget)
if (!self->target)
{
return;
}

target = G_PickTarget(self->killtarget);
self->movetarget = G_PickTarget(self->target);

if (!target || !target->use)
if (!self->movetarget)
{
return;
}

/* TODO: Fully implement target camera logic */
target->use(target, self, activator);
level.intermissiontime = level.time;
level.exitintermission = 0;

/* spawn fake player dummy where we were */
if (activator->client)
{
edict_t *dummy;

dummy = self->enemy = G_Spawn();
dummy->owner = activator;
dummy->clipmask = activator->clipmask;
VectorCopy(activator->s.origin, dummy->s.origin);
VectorCopy(activator->s.angles, dummy->s.angles);
dummy->groundentity = activator->groundentity;
dummy->groundentity_linkcount = dummy->groundentity ? dummy->groundentity->linkcount : 0;
dummy->think = target_camera_dummy_think;
dummy->nextthink = level.time + FRAMETIME;
dummy->solid = SOLID_BBOX;
dummy->movetype = MOVETYPE_STEP;
VectorCopy(activator->mins, dummy->mins);
VectorCopy(activator->maxs, dummy->maxs);
dummy->s.modelindex = dummy->s.modelindex2 = CUSTOM_PLAYER_MODEL;
dummy->s.skinnum = activator->s.skinnum;
VectorCopy(activator->velocity, dummy->velocity);
dummy->s.renderfx = RF_MINLIGHT;
dummy->s.frame = activator->s.frame;
gi.linkentity(dummy);
}

camera_lookat_pathtarget(self, self->s.origin, &level.intermission_angle);
VectorCopy(self->s.origin, level.intermission_origin);

/* move all clients to the intermission point */
for (i = 0; i < game.maxclients; i++)
{
edict_t* client = g_edicts + 1 + i;
if (!client->inuse)
{
continue;
}

/* respawn any dead clients */
if (client->health <= 0)
{
respawn(client);
}

MoveClientToIntermission(client);
}

self->activator = activator;
self->think = update_target_camera_think;
self->nextthink = level.time + self->wait;
self->moveinfo.move_speed = self->speed;

VectorSubtract(self->movetarget->s.origin, self->s.origin, diff);

self->moveinfo.remaining_distance = VectorNormalize(diff);
self->moveinfo.distance = self->moveinfo.remaining_distance;
}

void
Expand Down
1 change: 1 addition & 0 deletions src/game/header/local.h
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,7 @@ void ServerCommand(void);
qboolean SV_FilterPacket(char *from);

/* p_view.c */
void G_SetClientFrame(edict_t *ent, float speed);
void ClientEndServerFrame(edict_t *ent);

/* p_hud.c */
Expand Down
9 changes: 7 additions & 2 deletions src/game/player/view.c
Original file line number Diff line number Diff line change
Expand Up @@ -1329,7 +1329,7 @@ G_SetClientSound(edict_t *ent)
}

void
G_SetClientFrame(edict_t *ent)
G_SetClientFrame(edict_t *ent, float speed)
{
gclient_t *client;
qboolean duck, run;
Expand All @@ -1344,6 +1344,11 @@ G_SetClientFrame(edict_t *ent)
return; /* not in the player model */
}

if (speed)
{
xyspeed = speed;
}

client = ent->client;

if (client->ps.pmove.pm_flags & PMF_DUCKED)
Expand Down Expand Up @@ -1615,7 +1620,7 @@ ClientEndServerFrame(edict_t *ent)
G_SetClientEvent(ent);
G_SetClientEffects(ent);
G_SetClientSound(ent);
G_SetClientFrame(ent);
G_SetClientFrame(ent, 0);

VectorCopy(ent->velocity, ent->client->oldvelocity);
VectorCopy(ent->client->ps.viewangles, ent->client->oldviewangles);
Expand Down
2 changes: 2 additions & 0 deletions src/game/savegame/tables/gamefunc_decs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1356,6 +1356,7 @@ extern void tarbaby_stand ( edict_t * self ) ;
extern void tarbaby_touch ( edict_t * self , edict_t * other , cplane_t *plane, csurface_t *surf);
extern void target_actor_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ;
extern void target_anger_use ( edict_t * self , edict_t * other , edict_t * activator ) ;
extern void target_camera_dummy_think ( edict_t * self ) ;
extern void target_crosslevel_target_think ( edict_t * self ) ;
extern void target_earthquake_think ( edict_t * self ) ;
extern void target_earthquake_use ( edict_t * self , edict_t * other , edict_t * activator ) ;
Expand Down Expand Up @@ -1454,6 +1455,7 @@ extern void use_target_splash ( edict_t * self , edict_t * other , edict_t * act
extern void use_target_steam ( edict_t * self , edict_t * other , edict_t * activator ) ;
extern void use_target_soundfx ( edict_t *self, edict_t *other, edict_t *activator ) ;
extern void use_target_gravity ( edict_t *self, edict_t *other, edict_t *activator ) ;
extern void update_target_camera_think ( edict_t *self);
extern void update_target_soundfx ( edict_t *self);
extern void vengeance_pain ( edict_t * self , edict_t * other , float kick , int damage ) ;
extern void vengeance_think ( edict_t * self ) ;
Expand Down
2 changes: 2 additions & 0 deletions src/game/savegame/tables/gamefunc_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -1351,6 +1351,7 @@
{"target_actor_touch", (byte *)target_actor_touch},
{"target_anger_use", (byte *)target_anger_use},
{"target_angle", (byte *)target_angle},
{"target_camera_dummy_think", (byte *)target_camera_dummy_think},
{"target_crosslevel_target_think", (byte *)target_crosslevel_target_think},
{"target_earthquake_think", (byte *)target_earthquake_think},
{"target_earthquake_use", (byte *)target_earthquake_use},
Expand Down Expand Up @@ -1449,6 +1450,7 @@
{"use_target_splash", (byte *)use_target_splash},
{"use_target_steam", (byte *)use_target_steam},
{"use_target_gravity", (byte *)use_target_gravity},
{"update_target_camera_think", (byte *)update_target_camera_think},
{"update_target_soundfx", (byte *)update_target_soundfx},
{"use_target_soundfx", (byte *)use_target_soundfx},
{"vengeance_pain", (byte *)vengeance_pain},
Expand Down

0 comments on commit fd4a7ab

Please sign in to comment.