mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-01-10 00:34:32 +00:00
Merge remote-tracking branch 'origin/duel-stuff'
This commit is contained in:
commit
f3545a6e6f
16 changed files with 489 additions and 58 deletions
|
|
@ -139,7 +139,7 @@ skins
|
|||
// Gametypes
|
||||
gametypes
|
||||
{
|
||||
-1 = "Single Player";
|
||||
-1 = "Grand Prix";
|
||||
0 = "Race";
|
||||
1 = "Battle";
|
||||
}
|
||||
|
|
@ -5113,6 +5113,7 @@ thingtypes
|
|||
height = 92;
|
||||
}
|
||||
}
|
||||
|
||||
waypoints
|
||||
{
|
||||
color = 4; // Red
|
||||
|
|
@ -5161,6 +5162,80 @@ thingtypes
|
|||
fixedrotation = 1;
|
||||
}
|
||||
}
|
||||
|
||||
duel
|
||||
{
|
||||
color = 4; // Red
|
||||
arrow = 0;
|
||||
title = "Duel Objects";
|
||||
sprite = "SPBMA2A8";
|
||||
flags1text = "[1] Spawn in all modes";
|
||||
|
||||
2050
|
||||
{
|
||||
title = "Duel Bomb";
|
||||
width = 24;
|
||||
height = 48;
|
||||
arrow = 1;
|
||||
flags8text = "[8] Flip strafe";
|
||||
}
|
||||
|
||||
2051
|
||||
{
|
||||
title = "Banana";
|
||||
sprite = "BANAA2A8";
|
||||
width = 16;
|
||||
height = 32;
|
||||
}
|
||||
|
||||
2052
|
||||
{
|
||||
title = "Eggman Item";
|
||||
sprite = "FITMA0";
|
||||
width = 24;
|
||||
height = 32;
|
||||
}
|
||||
|
||||
2053
|
||||
{
|
||||
title = "Proximity Mine";
|
||||
sprite = "SSMNA0";
|
||||
width = 16;
|
||||
height = 24;
|
||||
}
|
||||
|
||||
2054
|
||||
{
|
||||
title = "Land Mine";
|
||||
sprite = "LNDMALAR";
|
||||
width = 24;
|
||||
height = 32;
|
||||
}
|
||||
|
||||
2055
|
||||
{
|
||||
title = "Hyudoro";
|
||||
sprite = "HYUUA2A8";
|
||||
width = 32;
|
||||
height = 24;
|
||||
}
|
||||
|
||||
2056
|
||||
{
|
||||
title = "Drop Target";
|
||||
sprite = "DTRGALAR";
|
||||
width = 45;
|
||||
height = 32;
|
||||
}
|
||||
|
||||
2057
|
||||
{
|
||||
title = "Pogo Spring";
|
||||
sprite = "POGSA0";
|
||||
width = 48;
|
||||
height = 32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Default things filters
|
||||
|
|
@ -5183,24 +5258,6 @@ thingsfilters
|
|||
}
|
||||
|
||||
filter2
|
||||
{
|
||||
name = "Enemies";
|
||||
category = "enemies";
|
||||
type = -1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
filter3
|
||||
{
|
||||
name = "NiGHTS Track";
|
||||
category = "nightstrk";
|
||||
type = -1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
filter4
|
||||
{
|
||||
name = "Normal Gravity";
|
||||
category = "";
|
||||
|
|
@ -5213,8 +5270,7 @@ thingsfilters
|
|||
|
||||
}
|
||||
|
||||
|
||||
filter5
|
||||
filter3
|
||||
{
|
||||
name = "Reverse Gravity";
|
||||
category = "";
|
||||
|
|
@ -5226,11 +5282,4 @@ thingsfilters
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
filter6
|
||||
{
|
||||
name = "Boss Waypoints";
|
||||
category = "";
|
||||
type = 292;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5372,6 +5372,8 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
|
|||
"MT_SINK_SHIELD",
|
||||
"MT_SINKTRAIL",
|
||||
|
||||
"MT_DUELBOMB", // Duel mode bombs
|
||||
|
||||
"MT_BATTLEBUMPER", // Battle Mode bumper
|
||||
"MT_BATTLEBUMPER_DEBRIS",
|
||||
"MT_BATTLEBUMPER_BLAST",
|
||||
|
|
|
|||
|
|
@ -669,6 +669,7 @@ extern boolean thwompsactive;
|
|||
extern UINT8 lastLowestLap;
|
||||
extern SINT8 spbplace;
|
||||
extern boolean rainbowstartavailable;
|
||||
extern boolean inDuel;
|
||||
|
||||
extern tic_t bombflashtimer; // Used to avoid causing seizures if multiple mines explode close to you :)
|
||||
extern boolean legitimateexit;
|
||||
|
|
|
|||
|
|
@ -312,6 +312,7 @@ boolean thwompsactive; // Thwomps activate on lap 2
|
|||
UINT8 lastLowestLap; // Last lowest lap, for activating race lap executors
|
||||
SINT8 spbplace; // SPB exists, give the person behind better items
|
||||
boolean rainbowstartavailable; // Boolean, keeps track of if the rainbow start was gotten
|
||||
boolean inDuel; // Boolean, keeps track of if it is a 1v1
|
||||
|
||||
// Client-sided, unsynched variables (NEVER use in anything that needs to be synced with other players)
|
||||
tic_t bombflashtimer = 0; // Cooldown before another FlashPal can be intialized by a bomb exploding near a displayplayer. Avoids seizures.
|
||||
|
|
|
|||
41
src/info.c
41
src/info.c
|
|
@ -8315,7 +8315,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
},
|
||||
|
||||
{ // MT_POGOSPRING
|
||||
-1, // doomednum
|
||||
2057, // doomednum
|
||||
S_POGOSPRING1, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_POGOSPRING2B, // seestate
|
||||
|
|
@ -23317,7 +23317,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
},
|
||||
|
||||
{ // MT_EGGMANITEM
|
||||
-1, // doomednum
|
||||
2052, // doomednum
|
||||
S_EGGMANITEM1, // spawnstate
|
||||
2, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
|
|
@ -23371,7 +23371,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
},
|
||||
|
||||
{ // MT_BANANA
|
||||
-1, // doomednum
|
||||
2051, // doomednum
|
||||
S_BANANA, // spawnstate
|
||||
2, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
|
|
@ -23560,7 +23560,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
},
|
||||
|
||||
{ // MT_SSMINE
|
||||
-1, // doomednum
|
||||
2053, // doomednum
|
||||
S_SSMINE_AIR1, // spawnstate
|
||||
1, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
|
|
@ -23695,7 +23695,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
},
|
||||
|
||||
{ // MT_LANDMINE
|
||||
-1, // doomednum
|
||||
2054, // doomednum
|
||||
S_LANDMINE, // spawnstate
|
||||
2, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
|
|
@ -23722,7 +23722,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
},
|
||||
|
||||
{ // MT_DROPTARGET
|
||||
-1, // doomednum
|
||||
2056, // doomednum
|
||||
S_DROPTARGET, // spawnstate
|
||||
3, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
|
|
@ -24154,7 +24154,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
},
|
||||
|
||||
{ // MT_HYUDORO_CENTER
|
||||
-1, // doomednum
|
||||
2055, // doomednum
|
||||
S_INVISIBLE, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
|
|
@ -24423,6 +24423,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_DUELBOMB
|
||||
2050, // doomednum
|
||||
S_SPB1, // 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
|
||||
64*FRACUNIT, // speed
|
||||
24*FRACUNIT, // radius
|
||||
48*FRACUNIT, // height
|
||||
0, // display offset
|
||||
0, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SPECIAL|MF_DONTENCOREMAP|MF_APPLYTERRAIN, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_BATTLEBUMPER
|
||||
-1, // doomednum
|
||||
S_BATTLEBUMPER1,// spawnstate
|
||||
|
|
|
|||
|
|
@ -6418,6 +6418,8 @@ typedef enum mobj_type
|
|||
MT_SINK_SHIELD,
|
||||
MT_SINKTRAIL,
|
||||
|
||||
MT_DUELBOMB, // Duel mode bombs
|
||||
|
||||
MT_BATTLEBUMPER, // Battle Mode bumpers
|
||||
MT_BATTLEBUMPER_DEBRIS,
|
||||
MT_BATTLEBUMPER_BLAST,
|
||||
|
|
|
|||
|
|
@ -422,6 +422,7 @@ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing)
|
|||
case MT_BALLHOG:
|
||||
case MT_SPB:
|
||||
case MT_BUBBLESHIELDTRAP:
|
||||
case MT_DUELBOMB:
|
||||
K_AddDodgeObject(thing, side, 20);
|
||||
break;
|
||||
case MT_SHRINK_GUN:
|
||||
|
|
|
|||
53
src/k_kart.c
53
src/k_kart.c
|
|
@ -49,10 +49,53 @@
|
|||
// battlewanted is an array of the WANTED player nums, -1 for no player in that slot
|
||||
// mapreset is set when enough players fill an empty server
|
||||
|
||||
boolean K_IsDuelItem(mobjtype_t type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MT_DUELBOMB:
|
||||
case MT_BANANA:
|
||||
case MT_EGGMANITEM:
|
||||
case MT_SSMINE:
|
||||
case MT_LANDMINE:
|
||||
case MT_HYUDORO_CENTER:
|
||||
case MT_DROPTARGET:
|
||||
case MT_POGOSPRING:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
boolean K_DuelItemAlwaysSpawns(mapthing_t *mt)
|
||||
{
|
||||
return (mt->options & MTF_EXTRA);
|
||||
}
|
||||
|
||||
static void K_SpawnDuelOnlyItems(void)
|
||||
{
|
||||
mapthing_t *mt = NULL;
|
||||
size_t i;
|
||||
|
||||
mt = mapthings;
|
||||
for (i = 0; i < nummapthings; i++, mt++)
|
||||
{
|
||||
mobjtype_t type = P_GetMobjtype(mt->type);
|
||||
|
||||
if (K_IsDuelItem(type) == true
|
||||
&& K_DuelItemAlwaysSpawns(mt) == false)
|
||||
{
|
||||
P_SpawnMapThing(mt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void K_TimerReset(void)
|
||||
{
|
||||
starttime = introtime = 3;
|
||||
numbulbs = 1;
|
||||
inDuel = false;
|
||||
}
|
||||
|
||||
void K_TimerInit(void)
|
||||
|
|
@ -78,6 +121,9 @@ void K_TimerInit(void)
|
|||
numPlayers++;
|
||||
}
|
||||
|
||||
// 1v1 activates DUEL rules!
|
||||
inDuel = (numPlayers == 2);
|
||||
|
||||
if (numPlayers >= 2)
|
||||
{
|
||||
rainbowstartavailable = true;
|
||||
|
|
@ -106,6 +152,12 @@ void K_TimerInit(void)
|
|||
|
||||
// NOW you can try to spawn in the Battle capsules, if there's not enough players for a match
|
||||
K_BattleInit();
|
||||
|
||||
if (inDuel == true)
|
||||
{
|
||||
K_SpawnDuelOnlyItems();
|
||||
}
|
||||
|
||||
//CONS_Printf("numbulbs set to %d (%d players, %d spectators) on tic %d\n", numbulbs, numPlayers, numspec, leveltime);
|
||||
}
|
||||
|
||||
|
|
@ -1437,6 +1489,7 @@ fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against)
|
|||
break;
|
||||
case MT_ORBINAUT:
|
||||
case MT_ORBINAUT_SHIELD:
|
||||
case MT_DUELBOMB:
|
||||
if (against->player)
|
||||
weight = K_PlayerWeight(against, NULL);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -38,6 +38,9 @@ angle_t K_ReflectAngle(angle_t angle, angle_t against, fixed_t maxspeed, fixed_t
|
|||
|
||||
void K_RegisterKartStuff(void);
|
||||
|
||||
boolean K_IsDuelItem(mobjtype_t type);
|
||||
boolean K_DuelItemAlwaysSpawns(mapthing_t *mt);
|
||||
|
||||
void K_TimerReset(void);
|
||||
void K_TimerInit(void);
|
||||
UINT32 K_GetPlayerDontDrawFlag(player_t *player);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#define k_objects_H
|
||||
|
||||
/* Hyudoro */
|
||||
void Obj_InitHyudoroCenter(mobj_t *center, mobj_t *master);
|
||||
void Obj_HyudoroDeploy(mobj_t *master);
|
||||
void Obj_HyudoroThink(mobj_t *actor);
|
||||
void Obj_HyudoroCenterThink(mobj_t *actor);
|
||||
|
|
@ -47,4 +48,10 @@ void Obj_OrbinautJawzMoveHeld(player_t *player);
|
|||
void Obj_JawzThink(mobj_t *th);
|
||||
void Obj_JawzThrown(mobj_t *th, fixed_t finalSpeed, SINT8 dir);
|
||||
|
||||
/* Duel Bomb */
|
||||
void Obj_DuelBombThink(mobj_t *bomb);
|
||||
void Obj_DuelBombReverse(mobj_t *bomb);
|
||||
void Obj_DuelBombTouch(mobj_t *bomb, mobj_t *toucher);
|
||||
void Obj_DuelBombInit(mobj_t *bomb);
|
||||
|
||||
#endif/*k_objects_H*/
|
||||
|
|
|
|||
|
|
@ -6,3 +6,4 @@ spb.c
|
|||
manta-ring.c
|
||||
orbinaut.c
|
||||
jawz.c
|
||||
duel-bomb.c
|
||||
|
|
|
|||
97
src/objects/duel-bomb.c
Normal file
97
src/objects/duel-bomb.c
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2022 by Sally "TehRealSalt" Cochenour
|
||||
// Copyright (C) 2022 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file duel-bomb.c
|
||||
/// \brief Duel mode bombs.
|
||||
|
||||
#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"
|
||||
#include "../g_game.h"
|
||||
#include "../z_zone.h"
|
||||
#include "../k_waypoint.h"
|
||||
#include "../k_respawn.h"
|
||||
#include "../k_collide.h"
|
||||
|
||||
#define bomb_dir(o) ((o)->movedir)
|
||||
|
||||
static fixed_t GetBombSpeed(mobj_t *bomb)
|
||||
{
|
||||
return FixedMul(bomb->info->speed, bomb->scale);
|
||||
}
|
||||
|
||||
static void UpdateBombMovement(mobj_t *bomb)
|
||||
{
|
||||
const fixed_t spd = GetBombSpeed(bomb);
|
||||
bomb->momx = FixedMul(spd, FINECOSINE(bomb_dir(bomb) >> ANGLETOFINESHIFT));
|
||||
bomb->momy = FixedMul(spd, FINESINE(bomb_dir(bomb) >> ANGLETOFINESHIFT));
|
||||
}
|
||||
|
||||
void Obj_DuelBombThink(mobj_t *bomb)
|
||||
{
|
||||
boolean grounded = P_IsObjectOnGround(bomb);
|
||||
|
||||
if (grounded == true)
|
||||
{
|
||||
UpdateBombMovement(bomb);
|
||||
}
|
||||
}
|
||||
|
||||
void Obj_DuelBombReverse(mobj_t *bomb)
|
||||
{
|
||||
bomb_dir(bomb) += ANGLE_180;
|
||||
UpdateBombMovement(bomb);
|
||||
}
|
||||
|
||||
void Obj_DuelBombTouch(mobj_t *bomb, mobj_t *toucher)
|
||||
{
|
||||
player_t *player = toucher->player;
|
||||
mobj_t *boom = NULL;
|
||||
|
||||
if (bomb->health <= 0 || toucher->health <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (player->flashing > 0 || player->hyudorotimer > 0 || P_PlayerInPain(player))
|
||||
{
|
||||
// No interaction
|
||||
return;
|
||||
}
|
||||
|
||||
// Create explosion
|
||||
boom = P_SpawnMobjFromMobj(bomb, 0, 0, 0, MT_BOOMEXPLODE);
|
||||
boom->momz = 5 * boom->scale;
|
||||
boom->color = SKINCOLOR_KETCHUP;
|
||||
S_StartSound(boom, bomb->info->attacksound);
|
||||
|
||||
if (player->invincibilitytimer > 0
|
||||
|| K_IsBigger(toucher, bomb) == true
|
||||
|| player->flamedash > 0)
|
||||
{
|
||||
// Kill without damaging.
|
||||
P_KillMobj(bomb, toucher, toucher, DMG_NORMAL);
|
||||
return;
|
||||
}
|
||||
|
||||
P_DamageMobj(toucher, bomb, bomb, 1, DMG_TUMBLE);
|
||||
P_KillMobj(bomb, toucher, toucher, DMG_NORMAL);
|
||||
}
|
||||
|
||||
void Obj_DuelBombInit(mobj_t *bomb)
|
||||
{
|
||||
bomb_dir(bomb) = bomb->angle + ANGLE_90;
|
||||
UpdateBombMovement(bomb);
|
||||
}
|
||||
|
|
@ -1,3 +1,15 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2022 by James R.
|
||||
// Copyright (C) 2022 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file hyudoro.c
|
||||
/// \brief Hyudoro item code.
|
||||
|
||||
#include "../doomdef.h"
|
||||
#include "../doomstat.h"
|
||||
#include "../info.h"
|
||||
|
|
@ -7,6 +19,7 @@
|
|||
#include "../p_local.h"
|
||||
#include "../r_main.h"
|
||||
#include "../s_sound.h"
|
||||
#include "../g_game.h"
|
||||
|
||||
enum {
|
||||
HYU_PATROL,
|
||||
|
|
@ -39,11 +52,14 @@ K_ChangePlayerItem
|
|||
#define hyudoro_hover_stack(o) ((o)->threshold)
|
||||
#define hyudoro_next(o) ((o)->tracer)
|
||||
#define hyudoro_stackpos(o) ((o)->reactiontime)
|
||||
#define hyudoro_delivered(o) (hyudoro_itemtype(o) == KITEM_NONE)
|
||||
|
||||
// cannot be combined
|
||||
#define hyudoro_center(o) ((o)->target)
|
||||
#define hyudoro_target(o) ((o)->target)
|
||||
|
||||
#define hyudoro_stolefrom(o) ((o)->hnext)
|
||||
|
||||
#define hyudoro_center_max_radius(o) ((o)->threshold)
|
||||
#define hyudoro_center_master(o) ((o)->target)
|
||||
|
||||
|
|
@ -101,6 +117,16 @@ sine_bob
|
|||
sineofs + FINESINE(a >> ANGLETOFINESHIFT));
|
||||
}
|
||||
|
||||
static void
|
||||
bob_in_place
|
||||
( mobj_t * hyu,
|
||||
INT32 bob_speed)
|
||||
{
|
||||
sine_bob(hyu,
|
||||
(leveltime & (bob_speed - 1)) *
|
||||
(ANGLE_MAX / bob_speed), -(3*FRACUNIT/4));
|
||||
}
|
||||
|
||||
static void
|
||||
project_hyudoro (mobj_t *hyu)
|
||||
{
|
||||
|
|
@ -127,8 +153,6 @@ project_hyudoro (mobj_t *hyu)
|
|||
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
|
||||
|
|
@ -154,9 +178,7 @@ project_hyudoro_hover (mobj_t *hyu)
|
|||
hyu->pitch = target->pitch;
|
||||
hyu->roll = target->roll;
|
||||
|
||||
sine_bob(hyu,
|
||||
(leveltime & (bob_speed - 1)) *
|
||||
(ANGLE_MAX / bob_speed), -(3*FRACUNIT/4));
|
||||
bob_in_place(hyu, 64);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -173,6 +195,79 @@ spawn_hyudoro_shadow (mobj_t *hyu)
|
|||
P_SetTarget(&shadow->tracer, hyu);
|
||||
}
|
||||
|
||||
static mobj_t *
|
||||
find_duel_target (mobj_t *ignore)
|
||||
{
|
||||
mobj_t *ret = NULL;
|
||||
UINT8 bestPosition = UINT8_MAX;
|
||||
UINT8 i;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
player_t *player = NULL;
|
||||
|
||||
if (playeringame[i] == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
player = &players[i];
|
||||
if (player->spectator || player->exiting)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!player->mo || P_MobjWasRemoved(player->mo))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ignore != NULL && player->mo == ignore)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (player->position < bestPosition)
|
||||
{
|
||||
ret = player->mo;
|
||||
bestPosition = player->position;
|
||||
|
||||
if (bestPosition <= 1)
|
||||
{
|
||||
// Can't get any lower
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
do_confused (mobj_t *hyu)
|
||||
{
|
||||
// Hyudoro is confused.
|
||||
// Spin around, try to find a new target.
|
||||
|
||||
if (hyudoro_delivered(hyu))
|
||||
{
|
||||
// Already delivered, not confused
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to find new target
|
||||
P_SetTarget(&hyudoro_target(hyu),
|
||||
find_duel_target(hyudoro_stolefrom(hyu)));
|
||||
|
||||
// Spin in circles
|
||||
hyu->angle += ANGLE_45;
|
||||
|
||||
// Bob very fast
|
||||
bob_in_place(hyu, 32);
|
||||
|
||||
hyu->sprzoff += hyu->height;
|
||||
}
|
||||
|
||||
static void
|
||||
move_to_player (mobj_t *hyu)
|
||||
{
|
||||
|
|
@ -181,8 +276,11 @@ move_to_player (mobj_t *hyu)
|
|||
angle_t angle;
|
||||
fixed_t speed;
|
||||
|
||||
if (!target)
|
||||
if (!target || P_MobjWasRemoved(target))
|
||||
{
|
||||
do_confused(hyu);
|
||||
return;
|
||||
}
|
||||
|
||||
angle = R_PointToAngle2(
|
||||
hyu->x, hyu->y, target->x, target->y);
|
||||
|
|
@ -232,6 +330,9 @@ deliver_item (mobj_t *hyu)
|
|||
hyu->destscale = target->scale / 4;
|
||||
hyu->scalespeed =
|
||||
abs(hyu->scale - hyu->destscale) / hyu->tics;
|
||||
|
||||
// sets as already delivered
|
||||
hyudoro_itemtype(hyu) = KITEM_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -287,11 +388,14 @@ hyudoro_patrol_hit_player
|
|||
|
||||
mobj_t *center = hyudoro_center(hyu);
|
||||
|
||||
mobj_t *master = NULL;
|
||||
|
||||
if (!player)
|
||||
return false;
|
||||
|
||||
// Cannot hit its master
|
||||
if (toucher == get_hyudoro_master(hyu))
|
||||
master = get_hyudoro_master(hyu);
|
||||
if (toucher == master)
|
||||
return false;
|
||||
|
||||
// Don't punish a punished player
|
||||
|
|
@ -313,8 +417,15 @@ hyudoro_patrol_hit_player
|
|||
player->hyudorotimer = hyudorotime;
|
||||
player->stealingtimer = hyudorotime;
|
||||
|
||||
P_SetTarget(&hyudoro_target(hyu),
|
||||
hyudoro_center_master(center));
|
||||
P_SetTarget(&hyudoro_stolefrom(hyu), toucher);
|
||||
|
||||
if (master == NULL || P_MobjWasRemoved(master))
|
||||
{
|
||||
// if master is NULL, it is probably a DUEL
|
||||
master = find_duel_target(toucher);
|
||||
}
|
||||
|
||||
P_SetTarget(&hyudoro_target(hyu), master);
|
||||
|
||||
if (center)
|
||||
P_RemoveMobj(center);
|
||||
|
|
@ -388,11 +499,8 @@ hyudoro_hover_await_stack (mobj_t *hyu)
|
|||
}
|
||||
|
||||
void
|
||||
Obj_HyudoroDeploy (mobj_t *master)
|
||||
Obj_InitHyudoroCenter (mobj_t * center, 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);
|
||||
|
||||
|
|
@ -405,20 +513,30 @@ Obj_HyudoroDeploy (mobj_t *master)
|
|||
|
||||
center->radius = hyu->radius;
|
||||
|
||||
hyu->angle = master->angle;
|
||||
hyu->angle = center->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;
|
||||
if (master && !P_MobjWasRemoved(master) && master->player)
|
||||
{
|
||||
hyu->renderflags |= RF_DONTDRAW &
|
||||
~(K_GetPlayerDontDrawFlag(master->player));
|
||||
hyu->renderflags &= ~(K_GetPlayerDontDrawFlag(master->player));
|
||||
}
|
||||
|
||||
spawn_hyudoro_shadow(hyu); // this sucks btw
|
||||
}
|
||||
|
||||
void
|
||||
Obj_HyudoroDeploy (mobj_t *master)
|
||||
{
|
||||
mobj_t *center = P_SpawnMobjFromMobj(
|
||||
master, 0, 0, 0, MT_HYUDORO_CENTER);
|
||||
|
||||
center->angle = master->angle;
|
||||
Obj_InitHyudoroCenter(center, master);
|
||||
|
||||
S_StartSound(master, sfx_s3k92); // scary ghost noise
|
||||
}
|
||||
|
|
|
|||
|
|
@ -356,6 +356,11 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
Obj_SPBTouch(special, toucher);
|
||||
return;
|
||||
}
|
||||
case MT_DUELBOMB:
|
||||
{
|
||||
Obj_DuelBombTouch(special, toucher);
|
||||
return;
|
||||
}
|
||||
case MT_EMERALD:
|
||||
if (!P_CanPickupItem(player, 0))
|
||||
return;
|
||||
|
|
@ -1012,7 +1017,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
|||
{
|
||||
target->fuse = 2;
|
||||
}
|
||||
else
|
||||
else if (inDuel == false)
|
||||
{
|
||||
UINT8 i;
|
||||
|
||||
|
|
|
|||
72
src/p_mobj.c
72
src/p_mobj.c
|
|
@ -1707,7 +1707,13 @@ void P_XYMovement(mobj_t *mo)
|
|||
|
||||
if (walltransferred == false)
|
||||
{
|
||||
if (mo->flags & MF_SLIDEME)
|
||||
if (mo->type == MT_DUELBOMB)
|
||||
{
|
||||
P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_BUMP);
|
||||
Obj_DuelBombReverse(mo);
|
||||
xmove = ymove = 0;
|
||||
}
|
||||
else if (mo->flags & MF_SLIDEME)
|
||||
{
|
||||
P_SlideMove(mo);
|
||||
if (P_MobjWasRemoved(mo))
|
||||
|
|
@ -1759,13 +1765,13 @@ void P_XYMovement(mobj_t *mo)
|
|||
}
|
||||
break;
|
||||
|
||||
case MT_BUBBLESHIELDTRAP:
|
||||
S_StartSound(mo, sfx_s3k44); // Bubble bounce
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Bubble bounce
|
||||
if (mo->type == MT_BUBBLESHIELDTRAP)
|
||||
S_StartSound(mo, sfx_s3k44);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5132,6 +5138,7 @@ boolean P_IsKartFieldItem(INT32 type)
|
|||
case MT_POGOSPRING:
|
||||
case MT_SINK:
|
||||
case MT_DROPTARGET:
|
||||
case MT_DUELBOMB:
|
||||
return true;
|
||||
|
||||
default:
|
||||
|
|
@ -7008,6 +7015,11 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
case MT_LANDMINE:
|
||||
mobj->friction = ORIG_FRICTION/4;
|
||||
|
||||
if (mobj->target && mobj->target->player)
|
||||
mobj->color = mobj->target->player->skincolor;
|
||||
else
|
||||
mobj->color = SKINCOLOR_SAPPHIRE;
|
||||
|
||||
if (mobj->momx || mobj->momy || mobj->momz)
|
||||
{
|
||||
mobj_t *ghost = P_SpawnGhostMobj(mobj);
|
||||
|
|
@ -7066,6 +7078,11 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
case MT_SPBEXPLOSION:
|
||||
mobj->health--;
|
||||
break;
|
||||
case MT_DUELBOMB:
|
||||
{
|
||||
Obj_DuelBombThink(mobj);
|
||||
break;
|
||||
}
|
||||
case MT_EMERALD:
|
||||
{
|
||||
if (battleovertime.enabled >= 10*TICRATE)
|
||||
|
|
@ -9890,6 +9907,7 @@ static void P_DefaultMobjShadowScale(mobj_t *thing)
|
|||
case MT_SINK:
|
||||
case MT_ROCKETSNEAKER:
|
||||
case MT_SPB:
|
||||
case MT_DUELBOMB:
|
||||
thing->shadowscale = 3*FRACUNIT/2;
|
||||
break;
|
||||
case MT_BANANA_SHIELD:
|
||||
|
|
@ -11741,10 +11759,22 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i)
|
|||
break;
|
||||
}
|
||||
|
||||
if (inDuel == false)
|
||||
{
|
||||
if (K_IsDuelItem(i) == true
|
||||
&& K_DuelItemAlwaysSpawns(mthing) == false)
|
||||
{
|
||||
// Only spawns in Duels.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// No bosses outside of a combat situation.
|
||||
// (just in case we want boss arenas to do double duty as battle maps)
|
||||
if (!bossinfo.boss && (mobjinfo[i].flags & MF_BOSS))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (metalrecording) // Metal Sonic can't use these things.
|
||||
{
|
||||
|
|
@ -12903,6 +12933,33 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
|
|||
|
||||
// Increment no. of capsules on the map counter
|
||||
maptargets++;
|
||||
break;
|
||||
}
|
||||
case MT_DUELBOMB:
|
||||
{
|
||||
// Duel Bomb needs init to match real map thing's angle
|
||||
mobj->angle = FixedAngle(mthing->angle << FRACBITS);
|
||||
Obj_DuelBombInit(mobj);
|
||||
*doangle = false;
|
||||
break;
|
||||
}
|
||||
case MT_BANANA:
|
||||
{
|
||||
// Give Duel bananas a random angle
|
||||
mobj->angle = FixedMul(P_RandomFixed(PR_DECORATION), ANGLE_MAX);
|
||||
*doangle = false;
|
||||
break;
|
||||
}
|
||||
case MT_HYUDORO_CENTER:
|
||||
{
|
||||
Obj_InitHyudoroCenter(mobj, NULL);
|
||||
break;
|
||||
}
|
||||
case MT_POGOSPRING:
|
||||
{
|
||||
// Start as tumble version.
|
||||
mobj->reactiontime++;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
|
|
@ -12943,6 +13000,11 @@ static void P_SetAmbush(mobj_t *mobj)
|
|||
mobj->type != MT_NIGHTSBUMPER &&
|
||||
mobj->type != MT_STARPOST)
|
||||
mobj->flags2 |= MF2_AMBUSH;
|
||||
|
||||
if (mobj->type == MT_DUELBOMB)
|
||||
{
|
||||
Obj_DuelBombReverse(mobj);
|
||||
}
|
||||
}
|
||||
|
||||
static void P_SetObjectSpecial(mobj_t *mobj)
|
||||
|
|
|
|||
|
|
@ -4591,6 +4591,7 @@ static void P_NetArchiveMisc(boolean resending)
|
|||
WRITEUINT8(save_p, lastLowestLap);
|
||||
WRITESINT8(save_p, spbplace);
|
||||
WRITEUINT8(save_p, rainbowstartavailable);
|
||||
WRITEUINT8(save_p, inDuel);
|
||||
|
||||
WRITEUINT32(save_p, introtime);
|
||||
WRITEUINT32(save_p, starttime);
|
||||
|
|
@ -4750,6 +4751,7 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading)
|
|||
lastLowestLap = READUINT8(save_p);
|
||||
spbplace = READSINT8(save_p);
|
||||
rainbowstartavailable = (boolean)READUINT8(save_p);
|
||||
inDuel = (boolean)READUINT8(save_p);
|
||||
|
||||
introtime = READUINT32(save_p);
|
||||
starttime = READUINT32(save_p);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue