Hyudoro behaves properly without owner set

When it's placed by the level, it's given to whoever has the best position at time of stealing. Since this is meant for duels, this means always the other player.

This behavior is also used as a default whenever its owner gets unset for whatever reason.

If there is literally NO ONE (1P), then rotate in place violently.
This commit is contained in:
Sally Coolatta 2022-09-28 00:44:50 -04:00
parent 456c824abf
commit 13a77581c4

View file

@ -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)
@ -173,6 +189,82 @@ 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.
const INT32 bob_speed = 32;
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
sine_bob(hyu,
(leveltime & (bob_speed - 1)) *
(ANGLE_MAX / bob_speed), -(3*FRACUNIT/4));
hyu->sprzoff += hyu->height;
}
static void
move_to_player (mobj_t *hyu)
{
@ -181,8 +273,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 +327,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 +385,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 +414,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);