RingRacers/src/objects/servant-hand.c
toaster e6619df2d4 Servant Hand: Refactor to use its own thinker
Since it's already ticking for the sake of a fuse, make it handle its own movement/scaling as well.

Spawning is still handled by the player thinker (and can be blocked by hitlag), but this permits it to disappear when a player dies/disconnects the server.
2023-07-18 15:45:49 +01:00

135 lines
2.8 KiB
C

#include "../doomdef.h"
#include "../p_local.h"
#include "../p_mobj.h"
#include "../d_player.h"
#include "../k_kart.h"
#include "../k_objects.h"
#include "../v_video.h"
#include "../r_main.h"
#include "../g_game.h"
void Obj_ServantHandSpawning(player_t *player)
{
if (player->pflags & PF_WRONGWAY || player->pflags & PF_POINTME)
{
if (player->handtimer < TICRATE)
{
player->handtimer++;
if (player->hand == NULL && player->handtimer == TICRATE)
{
mobj_t *hand = P_SpawnMobj(
player->mo->x,
player->mo->y,
player->mo->z + player->mo->height + 30*mapobjectscale,
MT_SERVANTHAND
);
if (hand)
{
K_FlipFromObject(hand, player->mo);
hand->old_z = hand->z;
P_SetTarget(&hand->target, player->mo);
P_SetTarget(&player->hand, hand);
hand->fuse = 8;
}
}
}
}
else if (player->handtimer != 0)
{
player->handtimer--;
}
}
void Obj_ServantHandThink(mobj_t *hand)
{
UINT8 handtimer = 0;
player_t *player = NULL;
if (P_MobjWasRemoved(hand->target))
{
P_RemoveMobj(hand);
return;
}
if (hand->target->health && hand->target->player && hand->target->player->hand == hand)
{
player = hand->target->player;
handtimer = hand->target->player->handtimer;
}
{
const fixed_t handpokespeed = 4;
const fixed_t looping = handpokespeed - abs((hand->threshold % (handpokespeed*2)) - handpokespeed);
fixed_t xoffs = 0, yoffs = 0;
if (hand->fuse != 0)
{
;
}
else if (looping != 0)
{
xoffs = FixedMul(2 * looping * mapobjectscale, FINECOSINE(hand->angle >> ANGLETOFINESHIFT)),
yoffs = FixedMul(2 * looping * mapobjectscale, FINESINE(hand->angle >> ANGLETOFINESHIFT)),
hand->threshold++;
}
else if (handtimer == 0)
{
hand->fuse = 8;
}
else
{
hand->threshold++;
}
if (hand->fuse != 0)
{
if ((hand->fuse > 4) ^ (handtimer < TICRATE/2))
{
hand->spritexscale = FRACUNIT/3;
hand->spriteyscale = 3*FRACUNIT;
}
else
{
hand->spritexscale = 2*FRACUNIT;
hand->spriteyscale = FRACUNIT/2;
}
}
if (player != NULL)
{
hand->color = player->skincolor;
hand->angle = player->besthanddirection;
P_MoveOrigin(hand,
player->mo->x + xoffs,
player->mo->y + yoffs,
player->mo->z + player->mo->height + 30*mapobjectscale
);
K_FlipFromObject(hand, player->mo);
hand->sprzoff = player->mo->sprzoff;
hand->renderflags &= ~RF_DONTDRAW;
hand->renderflags |= (RF_DONTDRAW & ~K_GetPlayerDontDrawFlag(player));
}
}
}
void Obj_PointPlayersToXY(fixed_t x, fixed_t y)
{
for(int i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator || !players[i].mo)
continue;
angle_t angletotarget = R_PointToAngle2(
players[i].mo->x, players[i].mo->y,
x, y);
players[i].pflags |= PF_POINTME;
players[i].besthanddirection = angletotarget;
}
}