Hyudoro object code

This commit is contained in:
James R 2022-04-29 22:02:22 -07:00
parent 910ebe9d0f
commit c6e7fe2d29
7 changed files with 432 additions and 6 deletions

View file

@ -465,6 +465,7 @@ typedef struct player_s
UINT16 hyudorotimer; // Duration of the Hyudoro offroad effect itself
SINT8 stealingtimer; // if >0 you are stealing, if <0 you are being stolen from
mobj_t *hoverhyudoro; // First hyudoro hovering next to player
UINT16 sneakertimer; // Duration of a Sneaker Boost (from Sneakers or level boosters)
UINT8 numsneakers; // Number of stacked sneaker effects

View file

@ -24570,13 +24570,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
64*FRACUNIT, // radius
32*FRACUNIT, // height
32*FRACUNIT, // radius
24*FRACUNIT, // height
0, // display offset
0, // mass
0, // damage
sfx_None, // activesound
MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
MF_SPECIAL|MF_NOCLIP|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},

View file

@ -36,6 +36,7 @@
#include "k_hud.h"
#include "k_terrain.h"
#include "k_director.h"
#include "k_objects.h"
// SOME IMPORTANT VARIABLES DEFINED IN DOOMDEF.H:
// gamespeed is cc (0 for easy, 1 for normal, 2 for hard)
@ -5178,6 +5179,7 @@ static void K_FlameDashLeftoverSmoke(mobj_t *src)
}
}
#if 0
static void K_DoHyudoroSteal(player_t *player)
{
INT32 i, numplayers = 0;
@ -5255,6 +5257,7 @@ static void K_DoHyudoroSteal(player_t *player)
S_StartSound(NULL, sfx_s3k92);
}
}
#endif
void K_DoSneaker(player_t *player, INT32 type)
{
@ -9563,7 +9566,9 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
{
player->itemamount--;
K_DoHyudoroSteal(player); // yes. yes they do.
//K_DoHyudoroSteal(player); // yes. yes they do.
Obj_HyudoroDeploy(player->mo);
K_PlayAttackTaunt(player->mo);
}
break;
case KITEM_POGOSPRING:

1
src/objects/Sourcefile Normal file
View file

@ -0,0 +1 @@
hyudoro.c

402
src/objects/hyudoro.c Normal file
View file

@ -0,0 +1,402 @@
#include "../doomdef.h"
#include "../doomstat.h"
#include "../info.h"
#include "../k_kart.h"
#include "../k_objects.h"
#include "../m_random.h"
#include "../p_local.h"
#include "../r_main.h"
#include "../s_sound.h"
enum {
HYU_PATROL,
HYU_RETURN,
HYU_HOVER,
};
// TODO: make these general functions
static fixed_t
K_GetSpeed (mobj_t *mobj)
{
return FixedHypot(mobj->momx, mobj->momy);
}
static void
K_ChangePlayerItem
( player_t * player,
INT32 itemtype,
INT32 itemamount)
{
player->itemtype = itemtype;
player->itemamount = itemamount;
K_UnsetItemOut(player);
}
#define hyudoro_mode(o) ((o)->extravalue1)
#define hyudoro_itemtype(o) ((o)->movefactor)
#define hyudoro_itemcount(o) ((o)->movecount)
#define hyudoro_hover_stack(o) ((o)->threshold)
#define hyudoro_next(o) ((o)->tracer)
#define hyudoro_stackpos(o) ((o)->reactiontime)
// cannot be combined
#define hyudoro_center(o) ((o)->target)
#define hyudoro_target(o) ((o)->target)
#define hyudoro_center_max_radius(o) ((o)->threshold)
#define hyudoro_center_master(o) ((o)->target)
static angle_t
trace_angle (mobj_t *hyu)
{
mobj_t *center = hyu->target;
if (hyu->x != center->x || hyu->y != center->y)
{
return R_PointToAngle2(
center->x, center->y, hyu->x, hyu->y);
}
else
return hyu->angle;
}
static angle_t
get_look_angle (mobj_t *thing)
{
player_t *player = thing->player;
return player ? player->angleturn : thing->angle;
}
static boolean
is_hyudoro (mobj_t *thing)
{
return thing && thing->type == MT_HYUDORO;
}
static mobj_t *
get_hyudoro_master (mobj_t *hyu)
{
mobj_t *center = hyudoro_center(hyu);
return center ? hyudoro_center_master(center) : NULL;
}
static void
sine_bob
( mobj_t * hyu,
angle_t a,
fixed_t sineofs)
{
hyu->sprzoff = FixedMul(hyu->height,
sineofs + FINESINE(a >> ANGLETOFINESHIFT));
}
static void
project_hyudoro (mobj_t *hyu)
{
mobj_t *center = hyudoro_center(hyu);
angle_t angleStep = FixedMul(5 * ANG1,
FixedDiv(hyudoro_center_max_radius(center),
center->radius));
angle_t angle = trace_angle(hyu) + angleStep;
fixed_t d = center->radius;
fixed_t x = P_ReturnThrustX(center, angle, d);
fixed_t y = P_ReturnThrustY(center, angle, d);
hyu->momx = (center->x + x) - hyu->x;
hyu->momy = (center->y + y) - hyu->y;
hyu->angle = angle + ANGLE_90;
sine_bob(hyu, angle, FRACUNIT);
}
static void
project_hyudoro_hover (mobj_t *hyu)
{
const INT32 bob_speed = 64;
mobj_t *target = hyudoro_target(hyu);
// Turns a bit toward its target
angle_t ang = get_look_angle(target) + ANGLE_67h;
fixed_t rad = (target->radius * 2) + hyu->radius;
fixed_t zofs = hyudoro_stackpos(hyu) *
((target->height / 2) + (hyu->height * 2));
P_MoveOrigin(hyu,
target->x - P_ReturnThrustX(hyu, ang, rad),
target->y - P_ReturnThrustY(hyu, ang, rad),
target->z + (zofs * P_MobjFlip(target)));
// Cancel momentum from HYU_RETURN.
// (And anything else! I don't trust this game!!)
hyu->momx = 0;
hyu->momy = 0;
hyu->angle = ang;
// copies sprite tilting
hyu->pitch = target->pitch;
hyu->roll = target->roll;
sine_bob(hyu,
(leveltime & (bob_speed - 1)) *
(ANGLE_MAX / bob_speed), -(3*FRACUNIT/4));
}
static void
spawn_hyudoro_shadow (mobj_t *hyu)
{
mobj_t *shadow = P_SpawnMobjFromMobj(
hyu, 0, 0, 0, MT_SHADOW);
shadow->whiteshadow = true;
shadow->shadowscale = hyu->shadowscale;
hyu->shadowscale = 0;
P_SetTarget(&shadow->tracer, hyu);
}
static void
move_to_player (mobj_t *hyu)
{
mobj_t *target = hyudoro_target(hyu);
angle_t angle;
if (!target)
return;
angle = R_PointToAngle2(
hyu->x, hyu->y, target->x, target->y);
P_InstaThrust(hyu, angle, (hyu->radius / 2) +
max(hyu->radius, K_GetSpeed(target)));
hyu->z = target->z; // stay level with target
hyu->angle = angle;
}
static void
deliver_item (mobj_t *hyu)
{
mobj_t *target = hyudoro_target(hyu);
player_t *player = target->player;
P_SetTarget(&hyudoro_target(hyu), NULL);
K_ChangePlayerItem(player,
hyudoro_itemtype(hyu),
hyudoro_itemcount(hyu));
S_StartSound(target, sfx_itpick);
// Stop moving here
hyu->momx = 0;
hyu->momy = 0;
hyu->tics = 4;
hyu->destscale = target->scale / 4;
hyu->scalespeed =
abs(hyu->scale - hyu->destscale) / hyu->tics;
}
static void
append_hyudoro
( mobj_t ** head,
mobj_t * hyu)
{
INT32 lastpos = 0;
while (is_hyudoro(*head))
{
lastpos = hyudoro_stackpos(*head);
head = &hyudoro_next(*head);
}
hyudoro_stackpos(hyu) = lastpos + 1;
*head = hyu;
}
static boolean
hyudoro_patrol_hit_player
( mobj_t * hyu,
mobj_t * toucher)
{
player_t *player = toucher->player;
mobj_t *center = hyudoro_center(hyu);
if (!player)
return false;
// Cannot hit its master
if (toucher == get_hyudoro_master(hyu))
return false;
// Don't punish a punished player
if (player->hyudorotimer)
return false;
// NO ITEM?
if (!player->itemamount)
return false;
K_AddHitLag(toucher, TICRATE/2, true);
player->hyudorotimer = hyudorotime;
player->stealingtimer = hyudorotime;
hyudoro_mode(hyu) = HYU_RETURN;
hyudoro_itemtype(hyu) = player->itemtype;
hyudoro_itemcount(hyu) = player->itemamount;
K_ChangePlayerItem(player, KITEM_NONE, 0);
P_SetTarget(&hyudoro_target(hyu),
hyudoro_center_master(center));
if (center)
P_RemoveMobj(center);
hyu->renderflags &= ~(RF_DONTDRAW);
return true;
}
static boolean
hyudoro_return_hit_player
( mobj_t * hyu,
mobj_t * toucher)
{
player_t *player = toucher->player;
if (toucher != hyudoro_target(hyu))
return false;
// If the player already has an item, just hover beside
// them until they use/lose it.
if (player->itemamount || player->itemroulette)
{
hyudoro_mode(hyu) = HYU_HOVER;
append_hyudoro(&player->hoverhyudoro, hyu);
}
else
{
deliver_item(hyu);
}
return true;
}
void
Obj_HyudoroDeploy (mobj_t *master)
{
mobj_t *center = P_SpawnMobjFromMobj(
master, 0, 0, 0, MT_HYUDORO_CENTER);
mobj_t *hyu = P_SpawnMobjFromMobj(
center, 0, 0, 0, MT_HYUDORO);
// This allows a Lua override
if (!hyudoro_center_max_radius(center))
{
hyudoro_center_max_radius(center) =
128 * center->scale;
}
center->radius = hyu->radius;
P_InitAngle(hyu, master->angle);
P_SetTarget(&hyudoro_center(hyu), center);
P_SetTarget(&hyudoro_center_master(center), master);
hyudoro_mode(hyu) = HYU_PATROL;
// Set splitscreen player visibility
if (master->player)
{
hyu->renderflags |= RF_DONTDRAW &
~(K_GetPlayerDontDrawFlag(master->player));
}
spawn_hyudoro_shadow(hyu); // this sucks btw
S_StartSound(master, sfx_s3k92); // scary ghost noise
}
void
Obj_HyudoroThink (mobj_t *hyu)
{
// Might get set from clipping slopes
hyu->momz = 0;
switch (hyudoro_mode(hyu))
{
case HYU_PATROL:
if (hyudoro_center(hyu))
project_hyudoro(hyu);
if (leveltime & 1)
{
mobj_t *ghost = P_SpawnGhostMobj(hyu);
// Flickers every frame
ghost->extravalue1 = 1;
ghost->extravalue2 = 2;
// copy per-splitscreen-player visibility
ghost->renderflags =
(hyu->renderflags & RF_DONTDRAW);
ghost->tics = 8;
P_SetTarget(&ghost->tracer, hyu);
}
break;
case HYU_RETURN:
move_to_player(hyu);
break;
case HYU_HOVER:
if (hyudoro_target(hyu))
project_hyudoro_hover(hyu);
break;
}
}
void
Obj_HyudoroCenterThink (mobj_t *center)
{
fixed_t max_radius = hyudoro_center_max_radius(center);
if (center->radius < max_radius)
center->radius += max_radius / 64;
}
void
Obj_HyudoroCollide
( mobj_t * hyu,
mobj_t * toucher)
{
switch (hyudoro_mode(hyu))
{
case HYU_PATROL:
hyudoro_patrol_hit_player(hyu, toucher);
break;
case HYU_RETURN:
hyudoro_return_hit_player(hyu, toucher);
break;
}
}

View file

@ -37,6 +37,7 @@
#include "k_boss.h"
#include "k_respawn.h"
#include "p_spec.h"
#include "k_objects.h"
// CTF player names
#define CTFTEAMCODE(pl) pl->ctfteam ? (pl->ctfteam == 1 ? "\x85" : "\x84") : ""
@ -483,6 +484,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
S_StartSound(toucher, sfx_s1b2);
return;
case MT_HYUDORO:
Obj_HyudoroCollide(special, toucher);
return;
case MT_RING:
case MT_FLINGRING:
if (special->extravalue1)

View file

@ -42,6 +42,7 @@
#include "k_respawn.h"
#include "k_bot.h"
#include "k_terrain.h"
#include "k_objects.h"
static CV_PossibleValue_t CV_BobSpeed[] = {{0, "MIN"}, {4*FRACUNIT, "MAX"}, {0, NULL}};
consvar_t cv_movebob = CVAR_INIT ("movebob", "1.0", CV_FLOAT|CV_SAVE, CV_BobSpeed, NULL);
@ -6559,8 +6560,8 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
}
else if (P_IsObjectOnGround(mobj))
{
mobj->momx = 1;
mobj->momy = 0;
//mobj->momx = 1;
//mobj->momy = 0;
mobj->flags &= ~MF_NOCLIPTHING;
mobj->flags |= MF_NOGRAVITY;
}
@ -7717,6 +7718,16 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
}
break;
}
case MT_HYUDORO:
{
Obj_HyudoroThink(mobj);
break;
}
case MT_HYUDORO_CENTER:
{
Obj_HyudoroCenterThink(mobj);
break;
}
case MT_ROCKETSNEAKER:
if (!mobj->target || !mobj->target->health)
{
@ -9671,6 +9682,7 @@ static void P_DefaultMobjShadowScale(mobj_t *thing)
case MT_SSMINE_SHIELD:
case MT_LANDMINE:
case MT_BALLHOG:
case MT_HYUDORO:
case MT_SINK:
case MT_ROCKETSNEAKER:
case MT_SPB: