mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge branch 'hyu'
This commit is contained in:
commit
dac2f4495e
18 changed files with 669 additions and 33 deletions
|
|
@ -302,6 +302,7 @@ target_compile_definitions(SRB2SDL2 PRIVATE -DCMAKECONFIG)
|
|||
#)
|
||||
|
||||
add_subdirectory(sdl)
|
||||
add_subdirectory(objects)
|
||||
|
||||
if(${CMAKE_SYSTEM} MATCHES Windows)
|
||||
add_subdirectory(win32)
|
||||
|
|
|
|||
|
|
@ -208,6 +208,7 @@ objdir:=$(makedir)/objs
|
|||
sources+=\
|
||||
$(call List,Sourcefile)\
|
||||
$(call List,blua/Sourcefile)\
|
||||
$(call List,objects/Sourcefile)\
|
||||
|
||||
depends:=$(basename $(filter %.c %.s,$(sources)))
|
||||
objects:=$(basename $(filter %.c %.s %.nas,$(sources)))
|
||||
|
|
|
|||
|
|
@ -469,6 +469,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
|
||||
|
|
|
|||
|
|
@ -368,8 +368,8 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
|
|||
"S_XDEATHSTATE",
|
||||
"S_RAISESTATE",
|
||||
|
||||
// Thok
|
||||
"S_THOK",
|
||||
"S_SHADOW",
|
||||
|
||||
// SRB2kart Frames
|
||||
"S_KART_STILL",
|
||||
|
|
@ -3745,6 +3745,9 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
|
|||
"S_FLAMESHIELDLINE3",
|
||||
"S_FLAMESHIELDFLASH",
|
||||
|
||||
// Caked-Up Booty-Sheet Ghost
|
||||
"S_HYUDORO",
|
||||
|
||||
// The legend
|
||||
"S_SINK",
|
||||
"S_SINK_SHIELD",
|
||||
|
|
@ -4493,6 +4496,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
|
|||
"MT_UNKNOWN",
|
||||
|
||||
"MT_THOK", // Thok! mobj
|
||||
"MT_SHADOW", // Linkdraw Shadow (for invisible objects)
|
||||
"MT_PLAYER",
|
||||
"MT_KART_LEFTOVER",
|
||||
"MT_KART_TIRE",
|
||||
|
|
@ -5315,6 +5319,9 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
|
|||
"MT_FLAMESHIELDPAPER",
|
||||
"MT_BUBBLESHIELDTRAP",
|
||||
|
||||
"MT_HYUDORO",
|
||||
"MT_HYUDORO_CENTER",
|
||||
|
||||
"MT_SINK", // Kitchen Sink Stuff
|
||||
"MT_SINK_SHIELD",
|
||||
"MT_SINKTRAIL",
|
||||
|
|
|
|||
|
|
@ -685,7 +685,6 @@ extern boolean comeback;
|
|||
extern SINT8 battlewanted[4];
|
||||
extern tic_t wantedcalcdelay;
|
||||
extern tic_t indirectitemcooldown;
|
||||
extern tic_t hyubgone;
|
||||
extern tic_t mapreset;
|
||||
extern boolean thwompsactive;
|
||||
extern UINT8 lastLowestLap;
|
||||
|
|
|
|||
|
|
@ -314,7 +314,6 @@ SINT8 pickedvote; // What vote the host rolls
|
|||
SINT8 battlewanted[4]; // WANTED players in battle, worth x2 points
|
||||
tic_t wantedcalcdelay; // Time before it recalculates WANTED
|
||||
tic_t indirectitemcooldown; // Cooldown before any more Shrink, SPB, or any other item that works indirectly is awarded
|
||||
tic_t hyubgone; // Cooldown before hyudoro is allowed to be rerolled
|
||||
tic_t mapreset; // Map reset delay when enough players have joined an empty game
|
||||
boolean thwompsactive; // Thwomps activate on lap 2
|
||||
UINT8 lastLowestLap; // Last lowest lap, for activating race lap executors
|
||||
|
|
|
|||
86
src/info.c
86
src/info.c
|
|
@ -29,6 +29,7 @@
|
|||
char sprnames[NUMSPRITES + 1][5] =
|
||||
{
|
||||
"NULL", // invisible object
|
||||
"NONE", // invisible but still rendered
|
||||
"UNKN",
|
||||
|
||||
"THOK", // Thok! mobj
|
||||
|
|
@ -570,6 +571,7 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
"FLMP", // Flame Shield paper sprites
|
||||
"FLML", // Flame Shield speed lines
|
||||
"FLMF", // Flame Shield flash
|
||||
"HYUU", // Hyudoro
|
||||
"SINK", // Kitchen Sink
|
||||
"SITR", // Kitchen Sink Trail
|
||||
"KBLN", // Battle Mode Bumper
|
||||
|
|
@ -856,6 +858,7 @@ state_t states[NUMSTATES] =
|
|||
{SPR_UNKN, FF_FULLBRIGHT, -1, {A_InfoState}, 6, 0, S_NULL}, // S_RAISESTATE
|
||||
|
||||
{SPR_THOK, FF_TRANS50, 8, {NULL}, 0, 0, S_NULL}, // S_THOK
|
||||
{SPR_NONE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SHADOW
|
||||
|
||||
// Player
|
||||
{SPR_PLAY, SPR2_STIN, 1, {NULL}, 0, 0, S_KART_STILL}, // S_KART_STILL
|
||||
|
|
@ -4300,6 +4303,8 @@ state_t states[NUMSTATES] =
|
|||
{SPR_FLML, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_ANIMATE|14, 7, {NULL}, 6, 1, S_NULL}, // S_FLAMESHIELDLINE3
|
||||
{SPR_FLMF, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_FLAMESHIELDFLASH
|
||||
|
||||
{SPR_HYUU, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_HYUDORO
|
||||
|
||||
{SPR_SINK, 0, 1, {A_SmokeTrailer}, MT_SINKTRAIL, 0, S_SINK}, // S_SINK
|
||||
{SPR_SINK, 0|FF_TRANS80|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_SINK_SHIELD}, // S_SINK_SHIELD
|
||||
{SPR_SITR, 0, 1, {NULL}, 0, 0, S_SINKTRAIL2}, // S_SINKTRAIL1
|
||||
|
|
@ -5154,6 +5159,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_SHADOW
|
||||
-1, // doomednum
|
||||
S_SHADOW, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
8, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
8, // speed
|
||||
32*FRACUNIT, // radius
|
||||
64*FRACUNIT, // height
|
||||
-1, // display offset
|
||||
16, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_PLAYER
|
||||
-1, // doomednum
|
||||
S_KART_STILL, // spawnstate
|
||||
|
|
@ -23881,6 +23913,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_HYUDORO
|
||||
-1, // doomednum
|
||||
S_HYUDORO, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
8, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
32*FRACUNIT, // radius
|
||||
24*FRACUNIT, // height
|
||||
0, // display offset
|
||||
0, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SPECIAL|MF_NOCLIP|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_HYUDORO_CENTER
|
||||
-1, // doomednum
|
||||
S_INVISIBLE, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
8, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
64*FRACUNIT, // radius
|
||||
32*FRACUNIT, // height
|
||||
0, // display offset
|
||||
0, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_SINK
|
||||
-1, // doomednum
|
||||
S_SINK, // spawnstate
|
||||
|
|
|
|||
11
src/info.h
11
src/info.h
|
|
@ -575,6 +575,7 @@ extern boolean actionsoverridden[NUMACTIONS];
|
|||
typedef enum sprite
|
||||
{
|
||||
SPR_NULL, // invisible object
|
||||
SPR_NONE, // invisible but still rendered
|
||||
SPR_UNKN,
|
||||
|
||||
SPR_THOK, // Thok! mobj
|
||||
|
|
@ -1116,6 +1117,7 @@ typedef enum sprite
|
|||
SPR_FLMP, // Flame Shield paper sprites
|
||||
SPR_FLML, // Flame Shield speed lines
|
||||
SPR_FLMF, // Flame Shield flash
|
||||
SPR_HYUU, // Hyudoro
|
||||
SPR_SINK, // Kitchen Sink
|
||||
SPR_SITR, // Kitchen Sink Trail
|
||||
SPR_KBLN, // Battle Mode Bumper
|
||||
|
|
@ -1355,8 +1357,8 @@ typedef enum state
|
|||
S_XDEATHSTATE,
|
||||
S_RAISESTATE,
|
||||
|
||||
// Thok
|
||||
S_THOK,
|
||||
S_SHADOW,
|
||||
|
||||
S_KART_STILL,
|
||||
S_KART_STILL_L,
|
||||
|
|
@ -4731,6 +4733,9 @@ typedef enum state
|
|||
S_FLAMESHIELDLINE3,
|
||||
S_FLAMESHIELDFLASH,
|
||||
|
||||
// Caked-Up Booty-Sheet Ghost
|
||||
S_HYUDORO,
|
||||
|
||||
// The legend
|
||||
S_SINK,
|
||||
S_SINK_SHIELD,
|
||||
|
|
@ -5516,6 +5521,7 @@ typedef enum mobj_type
|
|||
MT_UNKNOWN,
|
||||
|
||||
MT_THOK, // Thok! mobj
|
||||
MT_SHADOW, // Linkdraw Shadow (for invisible objects)
|
||||
MT_PLAYER,
|
||||
MT_KART_LEFTOVER,
|
||||
MT_KART_TIRE,
|
||||
|
|
@ -6338,6 +6344,9 @@ typedef enum mobj_type
|
|||
MT_FLAMESHIELDPAPER,
|
||||
MT_BUBBLESHIELDTRAP,
|
||||
|
||||
MT_HYUDORO,
|
||||
MT_HYUDORO_CENTER,
|
||||
|
||||
MT_SINK, // Kitchen Sink Stuff
|
||||
MT_SINK_SHIELD,
|
||||
MT_SINKTRAIL,
|
||||
|
|
|
|||
29
src/k_kart.c
29
src/k_kart.c
|
|
@ -38,6 +38,7 @@
|
|||
#include "k_director.h"
|
||||
#include "k_collide.h"
|
||||
#include "k_follower.h"
|
||||
#include "k_objects.h"
|
||||
|
||||
// SOME IMPORTANT VARIABLES DEFINED IN DOOMDEF.H:
|
||||
// gamespeed is cc (0 for easy, 1 for normal, 2 for hard)
|
||||
|
|
@ -353,25 +354,25 @@ static INT32 K_KartItemOddsRace[NUMKARTRESULTS-1][8] =
|
|||
//P-Odds 0 1 2 3 4 5 6 7
|
||||
/*Sneaker*/ { 0, 0, 2, 4, 6, 0, 0, 0 }, // Sneaker
|
||||
/*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 2, 4, 6 }, // Rocket Sneaker
|
||||
/*Invincibility*/ { 0, 0, 0, 0, 2, 4, 6, 9 }, // Invincibility
|
||||
/*Banana*/ { 4, 3, 1, 0, 0, 0, 0, 0 }, // Banana
|
||||
/*Invincibility*/ { 0, 0, 0, 0, 3, 4, 6, 9 }, // Invincibility
|
||||
/*Banana*/ { 2, 3, 1, 0, 0, 0, 0, 0 }, // Banana
|
||||
/*Eggman Monitor*/ { 1, 2, 0, 0, 0, 0, 0, 0 }, // Eggman Monitor
|
||||
/*Orbinaut*/ { 5, 4, 2, 2, 0, 0, 0, 0 }, // Orbinaut
|
||||
/*Jawz*/ { 0, 3, 2, 1, 1, 0, 0, 0 }, // Jawz
|
||||
/*Mine*/ { 0, 2, 3, 1, 0, 0, 0, 0 }, // Mine
|
||||
/*Land Mine*/ { 3, 0, 0, 0, 0, 0, 0, 0 }, // Land Mine
|
||||
/*Ballhog*/ { 0, 0, 2, 1, 0, 0, 0, 0 }, // Ballhog
|
||||
/*Ballhog*/ { 0, 0, 2, 2, 0, 0, 0, 0 }, // Ballhog
|
||||
/*Self-Propelled Bomb*/ { 0, 0, 0, 0, 0, 2, 4, 0 }, // Self-Propelled Bomb
|
||||
/*Grow*/ { 0, 0, 0, 1, 2, 3, 0, 0 }, // Grow
|
||||
/*Shrink*/ { 0, 0, 0, 0, 0, 0, 2, 0 }, // Shrink
|
||||
/*Lightning Shield*/ { 1, 2, 0, 0, 0, 0, 0, 0 }, // Lightning Shield
|
||||
/*Bubble Shield*/ { 0, 1, 2, 1, 0, 0, 0, 0 }, // Bubble Shield
|
||||
/*Flame Shield*/ { 0, 0, 0, 0, 0, 1, 3, 5 }, // Flame Shield
|
||||
/*Hyudoro*/ { 0, 0, 0, 1, 1, 0, 0, 0 }, // Hyudoro
|
||||
/*Hyudoro*/ { 3, 0, 0, 0, 0, 0, 0, 0 }, // Hyudoro
|
||||
/*Pogo Spring*/ { 0, 0, 0, 0, 0, 0, 0, 0 }, // Pogo Spring
|
||||
/*Super Ring*/ { 2, 1, 1, 0, 0, 0, 0, 0 }, // Super Ring
|
||||
/*Kitchen Sink*/ { 0, 0, 0, 0, 0, 0, 0, 0 }, // Kitchen Sink
|
||||
/*Drop Target*/ { 4, 0, 0, 0, 0, 0, 0, 0 }, // Drop Target
|
||||
/*Drop Target*/ { 3, 0, 0, 0, 0, 0, 0, 0 }, // Drop Target
|
||||
/*Sneaker x2*/ { 0, 0, 2, 2, 1, 0, 0, 0 }, // Sneaker x2
|
||||
/*Sneaker x3*/ { 0, 0, 0, 2, 6,10, 5, 0 }, // Sneaker x3
|
||||
/*Banana x3*/ { 0, 1, 1, 0, 0, 0, 0, 0 }, // Banana x3
|
||||
|
|
@ -458,9 +459,6 @@ static void K_KartGetItemResult(player_t *player, SINT8 getitem)
|
|||
if (getitem == KITEM_SPB || getitem == KITEM_SHRINK) // Indirect items
|
||||
indirectitemcooldown = 20*TICRATE;
|
||||
|
||||
if (getitem == KITEM_HYUDORO) // Hyudoro cooldown
|
||||
hyubgone = 5*TICRATE;
|
||||
|
||||
player->botvars.itemdelay = TICRATE;
|
||||
player->botvars.itemconfirm = 0;
|
||||
|
||||
|
|
@ -682,6 +680,7 @@ INT32 K_KartGetItemOdds(
|
|||
case KITEM_LANDMINE:
|
||||
case KITEM_DROPTARGET:
|
||||
case KITEM_BALLHOG:
|
||||
case KITEM_HYUDORO:
|
||||
case KRITEM_TRIPLESNEAKER:
|
||||
case KRITEM_TRIPLEORBINAUT:
|
||||
case KRITEM_QUADORBINAUT:
|
||||
|
|
@ -742,13 +741,6 @@ INT32 K_KartGetItemOdds(
|
|||
if (spbplace != -1)
|
||||
newodds = 0;
|
||||
break;
|
||||
case KITEM_HYUDORO:
|
||||
cooldownOnStart = true;
|
||||
notNearEnd = true;
|
||||
|
||||
if (hyubgone > 0)
|
||||
newodds = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -2917,6 +2909,7 @@ boolean K_TripwirePassConditions(player_t *player)
|
|||
player->sneakertimer ||
|
||||
player->growshrinktimer > 0 ||
|
||||
player->flamedash ||
|
||||
player->hyudorotimer ||
|
||||
player->speed > 2 * K_GetKartSpeed(player, false)
|
||||
)
|
||||
return true;
|
||||
|
|
@ -5393,6 +5386,7 @@ static void K_FlameDashLeftoverSmoke(mobj_t *src)
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void K_DoHyudoroSteal(player_t *player)
|
||||
{
|
||||
INT32 i, numplayers = 0;
|
||||
|
|
@ -5470,6 +5464,7 @@ static void K_DoHyudoroSteal(player_t *player)
|
|||
S_StartSound(NULL, sfx_s3k92);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void K_DoSneaker(player_t *player, INT32 type)
|
||||
{
|
||||
|
|
@ -10068,7 +10063,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:
|
||||
|
|
|
|||
11
src/k_objects.h
Normal file
11
src/k_objects.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/* object-specific code */
|
||||
#ifndef k_objects_H
|
||||
#define k_objects_H
|
||||
|
||||
/* Hyudoro */
|
||||
void Obj_HyudoroDeploy(mobj_t *master);
|
||||
void Obj_HyudoroThink(mobj_t *actor);
|
||||
void Obj_HyudoroCenterThink(mobj_t *actor);
|
||||
void Obj_HyudoroCollide(mobj_t *special, mobj_t *toucher);
|
||||
|
||||
#endif/*k_objects_H*/
|
||||
|
|
@ -378,9 +378,6 @@ int LUA_PushGlobals(lua_State *L, const char *word)
|
|||
} else if (fastcmp(word,"indirectitemcooldown")) {
|
||||
lua_pushinteger(L, indirectitemcooldown);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"hyubgone")) {
|
||||
lua_pushinteger(L, hyubgone);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"thwompsactive")) {
|
||||
lua_pushboolean(L, thwompsactive);
|
||||
return 1;
|
||||
|
|
@ -468,8 +465,6 @@ int LUA_WriteGlobals(lua_State *L, const char *word)
|
|||
exitcountdown = (tic_t)luaL_checkinteger(L, 2);
|
||||
else if (fastcmp(word,"indirectitemcooldown"))
|
||||
indirectitemcooldown = (tic_t)luaL_checkinteger(L, 2);
|
||||
else if (fastcmp(word,"hyubgone"))
|
||||
hyubgone = (tic_t)luaL_checkinteger(L, 2);
|
||||
else
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
1
src/objects/Sourcefile
Normal file
1
src/objects/Sourcefile
Normal file
|
|
@ -0,0 +1 @@
|
|||
hyudoro.c
|
||||
481
src/objects/hyudoro.c
Normal file
481
src/objects/hyudoro.c
Normal file
|
|
@ -0,0 +1,481 @@
|
|||
#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 player_t *
|
||||
get_hyudoro_target_player (mobj_t *hyu)
|
||||
{
|
||||
mobj_t *target = hyudoro_target(hyu);
|
||||
|
||||
return target ? target->player : 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);
|
||||
|
||||
if (player)
|
||||
{
|
||||
K_ChangePlayerItem(player,
|
||||
hyudoro_itemtype(hyu),
|
||||
player->itemamount + 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 void
|
||||
pop_hyudoro (mobj_t **head)
|
||||
{
|
||||
mobj_t *hyu = *head;
|
||||
|
||||
INT32 lastpos;
|
||||
INT32 thispos;
|
||||
|
||||
if (is_hyudoro(hyu))
|
||||
{
|
||||
lastpos = hyudoro_stackpos(hyu);
|
||||
hyu = hyudoro_next(hyu);
|
||||
|
||||
while (is_hyudoro(hyu))
|
||||
{
|
||||
thispos = hyudoro_stackpos(hyu);
|
||||
|
||||
hyudoro_stackpos(hyu) = lastpos;
|
||||
lastpos = thispos;
|
||||
|
||||
hyu = hyudoro_next(hyu);
|
||||
}
|
||||
}
|
||||
|
||||
*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);
|
||||
|
||||
hyudoro_mode(hyu) = HYU_RETURN;
|
||||
hyudoro_itemtype(hyu) = player->itemtype;
|
||||
hyudoro_itemcount(hyu) = player->itemamount;
|
||||
|
||||
K_StripItems(player);
|
||||
|
||||
player->hyudorotimer = hyudorotime;
|
||||
player->stealingtimer = hyudorotime;
|
||||
|
||||
P_SetTarget(&hyudoro_target(hyu),
|
||||
hyudoro_center_master(center));
|
||||
|
||||
if (center)
|
||||
P_RemoveMobj(center);
|
||||
|
||||
hyu->renderflags &= ~(RF_DONTDRAW);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean
|
||||
award_immediately (mobj_t *hyu)
|
||||
{
|
||||
player_t *player = get_hyudoro_target_player(hyu);
|
||||
|
||||
if (player)
|
||||
{
|
||||
if (player->itemamount &&
|
||||
player->itemtype != hyudoro_itemtype(hyu))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Same as picking up paper items; get stacks
|
||||
// immediately
|
||||
if (!P_CanPickupItem(player, 3))
|
||||
return false;
|
||||
}
|
||||
|
||||
deliver_item(hyu);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean
|
||||
hyudoro_return_hit_player
|
||||
( mobj_t * hyu,
|
||||
mobj_t * toucher)
|
||||
{
|
||||
if (toucher != hyudoro_target(hyu))
|
||||
return false;
|
||||
|
||||
// If the player already has an item, just hover beside
|
||||
// them until they use/lose it.
|
||||
if (!award_immediately(hyu))
|
||||
{
|
||||
hyudoro_mode(hyu) = HYU_HOVER;
|
||||
append_hyudoro(&toucher->player->hoverhyudoro, hyu);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean
|
||||
hyudoro_hover_await_stack (mobj_t *hyu)
|
||||
{
|
||||
player_t *player = get_hyudoro_target_player(hyu);
|
||||
|
||||
if (!player)
|
||||
return false;
|
||||
|
||||
// First in stack goes first
|
||||
if (hyu != player->hoverhyudoro)
|
||||
return false;
|
||||
|
||||
if (!award_immediately(hyu))
|
||||
return false;
|
||||
|
||||
pop_hyudoro(&player->hoverhyudoro);
|
||||
|
||||
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);
|
||||
hyudoro_hover_await_stack(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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
37
src/p_mobj.c
37
src/p_mobj.c
|
|
@ -44,6 +44,7 @@
|
|||
#include "k_bot.h"
|
||||
#include "k_terrain.h"
|
||||
#include "k_collide.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);
|
||||
|
|
@ -5300,6 +5301,20 @@ static void P_MobjSceneryThink(mobj_t *mobj)
|
|||
|
||||
switch (mobj->type)
|
||||
{
|
||||
case MT_SHADOW:
|
||||
if (mobj->tracer)
|
||||
{
|
||||
P_MoveOrigin(mobj,
|
||||
mobj->tracer->x,
|
||||
mobj->tracer->y,
|
||||
mobj->tracer->z);
|
||||
}
|
||||
else
|
||||
{
|
||||
P_RemoveMobj(mobj);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case MT_BOSSJUNK:
|
||||
mobj->renderflags ^= RF_DONTDRAW;
|
||||
break;
|
||||
|
|
@ -7671,6 +7686,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)
|
||||
{
|
||||
|
|
@ -9185,14 +9210,19 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
{
|
||||
if (mobj->extravalue2 >= 2)
|
||||
{
|
||||
UINT32 dontdraw = RF_DONTDRAW;
|
||||
|
||||
if (mobj->tracer)
|
||||
dontdraw &= ~(mobj->tracer->renderflags);
|
||||
|
||||
if (mobj->extravalue2 == 2) // I don't know why the normal logic doesn't work for this.
|
||||
mobj->renderflags ^= RF_DONTDRAW;
|
||||
mobj->renderflags ^= dontdraw;
|
||||
else
|
||||
{
|
||||
if (mobj->fuse == mobj->extravalue2)
|
||||
mobj->renderflags &= ~RF_DONTDRAW;
|
||||
mobj->renderflags &= ~(dontdraw);
|
||||
else
|
||||
mobj->renderflags |= RF_DONTDRAW;
|
||||
mobj->renderflags |= dontdraw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9653,6 +9683,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:
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ typedef enum
|
|||
FOLLOWER = 0x04,
|
||||
SKYBOXVIEW = 0x08,
|
||||
SKYBOXCENTER = 0x10,
|
||||
HOVERHYUDORO = 0x20,
|
||||
} player_saveflags;
|
||||
|
||||
static inline void P_ArchivePlayer(void)
|
||||
|
|
@ -196,6 +197,9 @@ static void P_NetArchivePlayers(void)
|
|||
if (players[i].skybox.centerpoint)
|
||||
flags |= SKYBOXCENTER;
|
||||
|
||||
if (players[i].hoverhyudoro)
|
||||
flags |= HOVERHYUDORO;
|
||||
|
||||
WRITEUINT16(save_p, flags);
|
||||
|
||||
if (flags & SKYBOXVIEW)
|
||||
|
|
@ -210,6 +214,9 @@ static void P_NetArchivePlayers(void)
|
|||
if (flags & FOLLOWITEM)
|
||||
WRITEUINT32(save_p, players[i].followmobj->mobjnum);
|
||||
|
||||
if (flags & HOVERHYUDORO)
|
||||
WRITEUINT32(save_p, players[i].hoverhyudoro->mobjnum);
|
||||
|
||||
WRITEUINT32(save_p, (UINT32)players[i].followitem);
|
||||
|
||||
WRITEUINT32(save_p, players[i].charflags);
|
||||
|
|
@ -485,6 +492,9 @@ static void P_NetUnArchivePlayers(void)
|
|||
if (flags & FOLLOWITEM)
|
||||
players[i].followmobj = (mobj_t *)(size_t)READUINT32(save_p);
|
||||
|
||||
if (flags & HOVERHYUDORO)
|
||||
players[i].hoverhyudoro = (mobj_t *)(size_t)READUINT32(save_p);
|
||||
|
||||
players[i].followitem = (mobjtype_t)READUINT32(save_p);
|
||||
|
||||
//SetPlayerSkinByNum(i, players[i].skin);
|
||||
|
|
@ -4236,6 +4246,13 @@ static void P_RelinkPointers(void)
|
|||
CONS_Debug(DBG_GAMELOGIC, "respawn.wp not found on %d\n", mobj->type);
|
||||
}
|
||||
}
|
||||
if (mobj->player->hoverhyudoro)
|
||||
{
|
||||
temp = (UINT32)(size_t)mobj->player->hoverhyudoro;
|
||||
mobj->player->hoverhyudoro = NULL;
|
||||
if (!P_SetTarget(&mobj->player->hoverhyudoro, P_FindNewPosition(temp)))
|
||||
CONS_Debug(DBG_GAMELOGIC, "hoverhyudoro not found on %d\n", mobj->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4488,7 +4505,6 @@ static void P_NetArchiveMisc(boolean resending)
|
|||
|
||||
WRITEUINT32(save_p, wantedcalcdelay);
|
||||
WRITEUINT32(save_p, indirectitemcooldown);
|
||||
WRITEUINT32(save_p, hyubgone);
|
||||
WRITEUINT32(save_p, mapreset);
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
@ -4638,7 +4654,6 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading)
|
|||
|
||||
wantedcalcdelay = READUINT32(save_p);
|
||||
indirectitemcooldown = READUINT32(save_p);
|
||||
hyubgone = READUINT32(save_p);
|
||||
mapreset = READUINT32(save_p);
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
|
|||
|
|
@ -4405,7 +4405,6 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
|
||||
wantedcalcdelay = wantedfrequency*2;
|
||||
indirectitemcooldown = 0;
|
||||
hyubgone = 0;
|
||||
mapreset = 0;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
|
|||
|
|
@ -685,8 +685,6 @@ void P_Ticker(boolean run)
|
|||
|
||||
if (indirectitemcooldown > 0)
|
||||
indirectitemcooldown--;
|
||||
if (hyubgone > 0)
|
||||
hyubgone--;
|
||||
|
||||
K_BossInfoTicker();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue