From 18c45d8a8ab66452738f4467b4e022b0c1d732f7 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Tue, 16 May 2023 23:36:38 -0700 Subject: [PATCH 01/29] WIP: Insta-"whip" --- src/d_player.h | 2 ++ src/deh_tables.c | 4 ++++ src/info.c | 31 +++++++++++++++++++++++++++++++ src/info.h | 6 ++++++ src/k_collide.cpp | 29 +++++++++++++++++++++++++++++ src/k_collide.h | 2 ++ src/k_kart.c | 15 +++++++++++++++ src/k_objects.h | 3 +++ src/lua_playerlib.c | 4 ++++ src/objects/CMakeLists.txt | 1 + src/objects/instawhip.c | 20 ++++++++++++++++++++ src/p_map.c | 8 +++++++- src/p_mobj.c | 5 +++++ src/p_saveg.c | 4 ++++ 14 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 src/objects/instawhip.c diff --git a/src/d_player.h b/src/d_player.h index a6aa69675..10a8c02e5 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -742,6 +742,8 @@ struct player_t mobj_t *stumbleIndicator; mobj_t *sliptideZipIndicator; + UINT8 instaShieldCooldown; + uint8_t public_key[PUBKEYLENGTH]; #ifdef HWRENDER diff --git a/src/deh_tables.c b/src/deh_tables.c index 63458676b..f9ad7fdad 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -3287,6 +3287,8 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_SLIPTIDEZIP", + "S_INSTAWHIP", + // Signpost sparkles "S_SIGNSPARK1", "S_SIGNSPARK2", @@ -5318,6 +5320,8 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_SLIPTIDEZIP", + "MT_INSTAWHIP", + "MT_SIGNSPARKLE", "MT_FASTLINE", diff --git a/src/info.c b/src/info.c index 3bfe157e3..caf458a3d 100644 --- a/src/info.c +++ b/src/info.c @@ -555,6 +555,8 @@ char sprnames[NUMSPRITES + 1][5] = "SLPT", // Sliptide zip indicator + "IWHP", // Instawhip + "WIPD", // Wipeout dust trail "DRIF", // Drift Sparks "BDRF", // Brake drift sparks @@ -3946,6 +3948,8 @@ state_t states[NUMSTATES] = {SPR_SLPT, FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_SLIPTIDEZIP + {SPR_IWHP, FF_FLOORSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_INSTAWHIP + {SPR_SGNS, FF_ADD|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_SIGNSPARK2}, // S_SIGNSPARK1 {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_SIGNSPARK3}, // S_SIGNSPARK2 {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_SIGNSPARK4}, // S_SIGNSPARK3 @@ -22632,6 +22636,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, + + { // MT_INSTAWHIP + -1, // doomednum + S_INSTAWHIP, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // 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 + 90*FRACUNIT, // radius + 90*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags + S_NULL // raisestate + }, { // MT_SIGNSPARKLE -1, // doomednum diff --git a/src/info.h b/src/info.h index cdb577e1b..10d35a0a8 100644 --- a/src/info.h +++ b/src/info.h @@ -1108,6 +1108,8 @@ typedef enum sprite SPR_SLPT, // Sliptide zip indicator + SPR_IWHP, // Instawhip + SPR_WIPD, // Wipeout dust trail SPR_DRIF, // Drift Sparks SPR_BDRF, // Brake drift sparks @@ -4357,6 +4359,8 @@ typedef enum state S_SLIPTIDEZIP, + S_INSTAWHIP, + // Signpost sparkles S_SIGNSPARK1, S_SIGNSPARK2, @@ -6423,6 +6427,8 @@ typedef enum mobj_type MT_MAGICIANBOX, MT_SLIPTIDEZIP, + MT_INSTAWHIP, + MT_SIGNSPARKLE, MT_FASTLINE, diff --git a/src/k_collide.cpp b/src/k_collide.cpp index 9bb2283be..43f3ee64b 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -787,6 +787,35 @@ boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2) return true; } +boolean K_InstaWhipCollide(mobj_t *t1, mobj_t *t2) +{ + if (t2->player) + { + if (t2 != t1->target && !P_PlayerInPain(t2->player) && t2->player->flashing == 0) + { + P_DamageMobj(t2, t1, t1, 1, DMG_NORMAL); + K_AddHitLag(t2, 10, true); + K_AddHitLag(t1->target, 2, false); + t1->hitlag = t1->target->hitlag; + return true; + } + return false; + } + else + { + if (t2->type == MT_ORBINAUT || t2->type == MT_JAWZ || t2->type == MT_GACHABOM + || t2->type == MT_BANANA || t2->type == MT_EGGMANITEM || t2->type == MT_BALLHOG + || t2->type == MT_SSMINE || t2->type == MT_LANDMINE || t2->type == MT_SINK + || t2->type == MT_GARDENTOP || t2->type == MT_DROPTARGET) + { + P_RemoveMobj(t2); + K_AddHitLag(t1->target, 2, false); + t1->hitlag = t1->target->hitlag; + } + return false; + } +} + boolean K_KitchenSinkCollide(mobj_t *t1, mobj_t *t2) { if (((t1->target == t2) || (!(t2->flags & (MF_ENEMY|MF_BOSS)) && (t1->target == t2->target))) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0))) diff --git a/src/k_collide.h b/src/k_collide.h index c93c72ed2..0f29ebf6b 100644 --- a/src/k_collide.h +++ b/src/k_collide.h @@ -24,6 +24,8 @@ boolean K_DropTargetCollide(mobj_t *t1, mobj_t *t2); void K_LightningShieldAttack(mobj_t *actor, fixed_t size); boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2); +boolean K_InstaWhipCollide(mobj_t *t1, mobj_t *t2); + boolean K_KitchenSinkCollide(mobj_t *t1, mobj_t *t2); boolean K_FallingRockCollide(mobj_t *t1, mobj_t *t2); diff --git a/src/k_kart.c b/src/k_kart.c index 91b2802ee..716a23bad 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7877,6 +7877,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->gateBoost) player->gateBoost--; + if (player->instaShieldCooldown) + player->instaShieldCooldown--; + if (player->startboost > 0 && onground == true) { player->startboost--; @@ -10530,6 +10533,18 @@ void K_MoveKartPlayer(player_t *player, boolean onground) // Ring boosting if (player->pflags & PF_USERINGS) { + if (ATTACK_IS_DOWN && player->rings <= 0 && players->instaShieldCooldown == 0) + { + player->instaShieldCooldown = 2*TICRATE/3; + S_StartSound(player->mo, sfx_join); + mobj_t *whip = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_INSTAWHIP); + P_SetScale(whip, player->mo->scale); + P_SetTarget(&whip->target, player->mo); + K_MatchGenericExtraFlags(whip, player->mo); + whip->fuse = 10; + player->flashing = max(player->flashing, 10); + } + if ((cmd->buttons & BT_ATTACK) && !player->ringdelay && player->rings > 0) { mobj_t *ring = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_RING); diff --git a/src/k_objects.h b/src/k_objects.h index 605206ec7..a7788d303 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -107,6 +107,9 @@ void Obj_LoopEndpointCollide(mobj_t *special, mobj_t *toucher); void Obj_BeginDropTargetMorph(mobj_t *target, skincolornum_t color); boolean Obj_DropTargetMorphThink(mobj_t *morph); +/* Instawhip */ +void Obj_InstaWhipThink(mobj_t *whip); + /* Ring Shooter */ boolean Obj_RingShooterThinker(mobj_t *mo); boolean Obj_PlayerRingShooterFreeze(player_t *const player); diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 4dc28ac18..39039e011 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -319,6 +319,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->sliptideZipDelay); else if (fastcmp(field,"sliptideZipBoost")) lua_pushinteger(L, plr->sliptideZipBoost); + else if (fastcmp(field,"instaShieldCooldown")) + lua_pushinteger(L, plr->instaShieldCooldown); /* else if (fastcmp(field,"itemroulette")) lua_pushinteger(L, plr->itemroulette); @@ -713,6 +715,8 @@ static int player_set(lua_State *L) plr->sliptideZipDelay = luaL_checkinteger(L, 3); else if (fastcmp(field,"sliptideZipBoost")) plr->sliptideZipBoost = luaL_checkinteger(L, 3); + else if (fastcmp(field,"instaShieldCooldown")) + plr->instaShieldCooldown = luaL_checkinteger(L, 3); /* else if (fastcmp(field,"itemroulette")) plr->itemroulette = luaL_checkinteger(L, 3); diff --git a/src/objects/CMakeLists.txt b/src/objects/CMakeLists.txt index df047fb5d..cb2f61519 100644 --- a/src/objects/CMakeLists.txt +++ b/src/objects/CMakeLists.txt @@ -17,4 +17,5 @@ target_sources(SRB2SDL2 PRIVATE ring-shooter.c audience.c random-item.c + instawhip.c ) diff --git a/src/objects/instawhip.c b/src/objects/instawhip.c new file mode 100644 index 000000000..30587c762 --- /dev/null +++ b/src/objects/instawhip.c @@ -0,0 +1,20 @@ +#include "../doomdef.h" +#include "../info.h" +#include "../k_objects.h" +#include "../p_local.h" + +void Obj_InstaWhipThink (mobj_t *whip) +{ + if (P_MobjWasRemoved(whip->target)) + { + P_RemoveMobj(whip); + } + else + { + whip->flags &= ~(MF_NOCLIPTHING); + P_MoveOrigin(whip, whip->target->x, whip->target->y, whip->target->z + whip->target->height/2); + whip->flags |= MF_NOCLIPTHING; + + P_SetScale(whip, whip->target->scale); + } +} \ No newline at end of file diff --git a/src/p_map.c b/src/p_map.c index 5b539ad28..d96afc08d 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -741,7 +741,13 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) return BMIT_ABORT; // stop moving } - // SRB2kart 011617 - Colission[sic] code for kart items //{ + // SRB2kart 011617 - Colission[sic] code for kart items // + + if (tm.thing->type == MT_INSTAWHIP) + { + K_InstaWhipCollide(tm.thing, thing); + return BMIT_CONTINUE; + } if (thing->type == MT_SPB) { diff --git a/src/p_mobj.c b/src/p_mobj.c index fbe4d90c2..98b9470a8 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8356,6 +8356,11 @@ static boolean P_MobjRegularThink(mobj_t *mobj) Obj_GardenTopThink(mobj); break; } + case MT_INSTAWHIP: + { + Obj_InstaWhipThink(mobj); + break; + } case MT_GARDENTOPSPARK: { Obj_GardenTopSparkThink(mobj); diff --git a/src/p_saveg.c b/src/p_saveg.c index 70ccf1624..46cf3afeb 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -419,6 +419,8 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEMEM(save->p, players[i].public_key, PUBKEYLENGTH); + WRITEUINT8(save->p, players[i].instaShieldCooldown); + // respawnvars_t WRITEUINT8(save->p, players[i].respawn.state); WRITEUINT32(save->p, K_GetWaypointHeapIndex(players[i].respawn.wp)); @@ -804,6 +806,8 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) READMEM(save->p, players[i].public_key, PUBKEYLENGTH); + players[i].instaShieldCooldown = READUINT8(save->p); + // respawnvars_t players[i].respawn.state = READUINT8(save->p); players[i].respawn.wp = (waypoint_t *)(size_t)READUINT32(save->p); From a3cc422706caa3758e63fce26d09d0df6b42bb70 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Wed, 17 May 2023 01:50:17 -0700 Subject: [PATCH 02/29] WIP: the sequel --- src/info.c | 2 +- src/k_collide.cpp | 9 ++++++--- src/k_kart.c | 31 ++++++++++++++++++++++--------- src/objects/instawhip.c | 9 +++++++++ src/objects/monitor.c | 5 ++++- src/sounds.c | 2 ++ src/sounds.h | 2 ++ 7 files changed, 46 insertions(+), 14 deletions(-) diff --git a/src/info.c b/src/info.c index caf458a3d..57713644e 100644 --- a/src/info.c +++ b/src/info.c @@ -3948,7 +3948,7 @@ state_t states[NUMSTATES] = {SPR_SLPT, FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_SLIPTIDEZIP - {SPR_IWHP, FF_FLOORSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_INSTAWHIP + {SPR_IWHP, FF_FLOORSPRITE|FF_ANIMATE|0, -1, {NULL}, 6, 2, S_NULL}, // S_INSTAWHIP {SPR_SGNS, FF_ADD|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_SIGNSPARK2}, // S_SIGNSPARK1 {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_SIGNSPARK3}, // S_SIGNSPARK2 diff --git a/src/k_collide.cpp b/src/k_collide.cpp index 43f3ee64b..3aebcf365 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -793,7 +793,9 @@ boolean K_InstaWhipCollide(mobj_t *t1, mobj_t *t2) { if (t2 != t1->target && !P_PlayerInPain(t2->player) && t2->player->flashing == 0) { - P_DamageMobj(t2, t1, t1, 1, DMG_NORMAL); + P_PlayRinglossSound(t2); + P_PlayerRingBurst(t2->player, 5); + P_DamageMobj(t2, t1, t1, 1, DMG_STUMBLE); K_AddHitLag(t2, 10, true); K_AddHitLag(t1->target, 2, false); t1->hitlag = t1->target->hitlag; @@ -806,9 +808,10 @@ boolean K_InstaWhipCollide(mobj_t *t1, mobj_t *t2) if (t2->type == MT_ORBINAUT || t2->type == MT_JAWZ || t2->type == MT_GACHABOM || t2->type == MT_BANANA || t2->type == MT_EGGMANITEM || t2->type == MT_BALLHOG || t2->type == MT_SSMINE || t2->type == MT_LANDMINE || t2->type == MT_SINK - || t2->type == MT_GARDENTOP || t2->type == MT_DROPTARGET) + || t2->type == MT_GARDENTOP || t2->type == MT_DROPTARGET || t2->type == MT_BATTLECAPSULE + || t2->type == MT_MONITOR) { - P_RemoveMobj(t2); + P_DamageMobj(t2, t1, t1, 1, DMG_NORMAL); K_AddHitLag(t1->target, 2, false); t1->hitlag = t1->target->hitlag; } diff --git a/src/k_kart.c b/src/k_kart.c index 716a23bad..bd50a31ed 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7878,7 +7878,12 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->gateBoost--; if (player->instaShieldCooldown) + { player->instaShieldCooldown--; + if (!P_IsObjectOnGround(player->mo)) + player->instaShieldCooldown = max(player->instaShieldCooldown, 1); + } + if (player->startboost > 0 && onground == true) { @@ -10533,16 +10538,24 @@ void K_MoveKartPlayer(player_t *player, boolean onground) // Ring boosting if (player->pflags & PF_USERINGS) { - if (ATTACK_IS_DOWN && player->rings <= 0 && players->instaShieldCooldown == 0) + if (ATTACK_IS_DOWN && player->rings <= 0) { - player->instaShieldCooldown = 2*TICRATE/3; - S_StartSound(player->mo, sfx_join); - mobj_t *whip = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_INSTAWHIP); - P_SetScale(whip, player->mo->scale); - P_SetTarget(&whip->target, player->mo); - K_MatchGenericExtraFlags(whip, player->mo); - whip->fuse = 10; - player->flashing = max(player->flashing, 10); + if (players->instaShieldCooldown) + { + S_StartSound(player->mo, sfx_s1a9); + } + else + { + player->instaShieldCooldown = 50; + S_StartSound(player->mo, sfx_iwhp); + mobj_t *whip = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_INSTAWHIP); + P_SetScale(whip, player->mo->scale); + P_SetTarget(&whip->target, player->mo); + K_MatchGenericExtraFlags(whip, player->mo); + whip->fuse = 12; // Changing instawhip animation duration? Look here + player->flashing = max(player->flashing, 12); + player->mo->momz += FRACUNIT; + } } if ((cmd->buttons & BT_ATTACK) && !player->ringdelay && player->rings > 0) diff --git a/src/objects/instawhip.c b/src/objects/instawhip.c index 30587c762..974ca70fd 100644 --- a/src/objects/instawhip.c +++ b/src/objects/instawhip.c @@ -15,6 +15,15 @@ void Obj_InstaWhipThink (mobj_t *whip) P_MoveOrigin(whip, whip->target->x, whip->target->y, whip->target->z + whip->target->height/2); whip->flags |= MF_NOCLIPTHING; + whip->angle = whip->target->angle + (ANG30 * 2 * whip->fuse); + + whip->renderflags |= RF_NOSPLATBILLBOARD; + + if (whip->renderflags & RF_DONTDRAW) + whip->renderflags &= ~RF_DONTDRAW; + else + whip->renderflags |= RF_DONTDRAW; + P_SetScale(whip, whip->target->scale); } } \ No newline at end of file diff --git a/src/objects/monitor.c b/src/objects/monitor.c index 8f5be65eb..fccb1a0f9 100644 --- a/src/objects/monitor.c +++ b/src/objects/monitor.c @@ -615,7 +615,10 @@ Obj_MonitorGetDamage } else { - damage = FRACUNIT; // kill instantly + if (inflictor->type == MT_INSTAWHIP) + damage = FRACUNIT/3; + else + damage = FRACUNIT; // kill instantly } return damage; diff --git a/src/sounds.c b/src/sounds.c index ebf43289a..2f5edb9c6 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -1184,6 +1184,8 @@ sfxinfo_t S_sfx[NUMSFX] = {"monch", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"etexpl", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Game crash"}, + {"iwhp", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Grow alarm + // SRB2Kart - Engine sounds // Engine class A {"krta00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, diff --git a/src/sounds.h b/src/sounds.h index 427731ec5..fda612893 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -1253,6 +1253,8 @@ typedef enum sfx_monch, sfx_etexpl, + sfx_iwhp, + // Next up: UNIQUE ENGINE SOUNDS! Hoooooo boy... // Engine class A - Low Speed, Low Weight sfx_krta00, From 466f7dece01fb003c8e04aca0d5d1f81e207ba7f Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Wed, 17 May 2023 13:47:37 -0700 Subject: [PATCH 03/29] Instawhip twirl --- src/objects/instawhip.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/objects/instawhip.c b/src/objects/instawhip.c index 974ca70fd..10f25fd43 100644 --- a/src/objects/instawhip.c +++ b/src/objects/instawhip.c @@ -11,19 +11,29 @@ void Obj_InstaWhipThink (mobj_t *whip) } else { + mobj_t *mo = whip->target; + player_t *player = mo->player; + + // Follow player whip->flags &= ~(MF_NOCLIPTHING); - P_MoveOrigin(whip, whip->target->x, whip->target->y, whip->target->z + whip->target->height/2); + P_SetScale(whip, whip->target->scale); + P_MoveOrigin(whip, mo->x, mo->y, mo->z + mo->height/2); whip->flags |= MF_NOCLIPTHING; + // Twirl whip->angle = whip->target->angle + (ANG30 * 2 * whip->fuse); + whip->target->player->drawangle = whip->angle; + if (player->follower) + player->follower->angle = whip->angle; + player->pflags |= PF_GAINAX; + player->glanceDir = -2; + // Visuals whip->renderflags |= RF_NOSPLATBILLBOARD; if (whip->renderflags & RF_DONTDRAW) whip->renderflags &= ~RF_DONTDRAW; else whip->renderflags |= RF_DONTDRAW; - - P_SetScale(whip, whip->target->scale); } } \ No newline at end of file From e189725fc3fbf866aed47d3debe07e5a365fd217 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Wed, 17 May 2023 14:01:11 -0700 Subject: [PATCH 04/29] Fix instawhip cooldown reminder --- src/k_kart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index bd50a31ed..5e618126e 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -10540,9 +10540,9 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { if (ATTACK_IS_DOWN && player->rings <= 0) { - if (players->instaShieldCooldown) + if (player->instaShieldCooldown) { - S_StartSound(player->mo, sfx_s1a9); + S_StartSound(player->mo, sfx_kc50); } else { From d68de3a0e5e69245910ffa210e25141fb81c1ae0 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Wed, 17 May 2023 14:06:37 -0700 Subject: [PATCH 05/29] Instawhip: Bump up attacker hitlag --- src/k_collide.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/k_collide.cpp b/src/k_collide.cpp index 3aebcf365..fa0a8ce14 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -789,6 +789,9 @@ boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2) boolean K_InstaWhipCollide(mobj_t *t1, mobj_t *t2) { + const int defenderHitlag = 10; + const int attackerHitlag = 4; + if (t2->player) { if (t2 != t1->target && !P_PlayerInPain(t2->player) && t2->player->flashing == 0) @@ -796,8 +799,8 @@ boolean K_InstaWhipCollide(mobj_t *t1, mobj_t *t2) P_PlayRinglossSound(t2); P_PlayerRingBurst(t2->player, 5); P_DamageMobj(t2, t1, t1, 1, DMG_STUMBLE); - K_AddHitLag(t2, 10, true); - K_AddHitLag(t1->target, 2, false); + K_AddHitLag(t2, defenderHitlag, true); + K_AddHitLag(t1->target, attackerHitlag, false); t1->hitlag = t1->target->hitlag; return true; } @@ -812,7 +815,7 @@ boolean K_InstaWhipCollide(mobj_t *t1, mobj_t *t2) || t2->type == MT_MONITOR) { P_DamageMobj(t2, t1, t1, 1, DMG_NORMAL); - K_AddHitLag(t1->target, 2, false); + K_AddHitLag(t1->target, attackerHitlag, false); t1->hitlag = t1->target->hitlag; } return false; From d95ceac1c46882632b0f27853e22b37b388cbd8a Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Wed, 17 May 2023 14:15:26 -0700 Subject: [PATCH 06/29] Instawhip charge restrictions --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 5e618126e..a8d7c207e 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -10540,7 +10540,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { if (ATTACK_IS_DOWN && player->rings <= 0) { - if (player->instaShieldCooldown) + if (player->instaShieldCooldown || leveltime < starttime || player->spindash) { S_StartSound(player->mo, sfx_kc50); } From 57e03e8a80c950b2c010132fa875cb988ef3abd3 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Wed, 17 May 2023 14:28:46 -0700 Subject: [PATCH 07/29] Instawhip monitor hack: one contact per whip --- src/k_collide.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/k_collide.cpp b/src/k_collide.cpp index fa0a8ce14..60a4d02b5 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -814,6 +814,15 @@ boolean K_InstaWhipCollide(mobj_t *t1, mobj_t *t2) || t2->type == MT_GARDENTOP || t2->type == MT_DROPTARGET || t2->type == MT_BATTLECAPSULE || t2->type == MT_MONITOR) { + // Monitor hack. We can hit monitors once per instawhip, no multihit shredding! + // Damage values in Obj_MonitorGetDamage. + if (t2->type == MT_MONITOR) + { + if (t1->extravalue1 != 1) + return false; + t1->extravalue1 = 1; + } + P_DamageMobj(t2, t1, t1, 1, DMG_NORMAL); K_AddHitLag(t1->target, attackerHitlag, false); t1->hitlag = t1->target->hitlag; From 1b16b3f777aaf96693b76374e6d6ae6957c0704e Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Thu, 18 May 2023 16:17:52 -0700 Subject: [PATCH 08/29] Instawhip: Damage sourcing and consistency fixes --- src/k_collide.cpp | 9 ++++++--- src/p_inter.c | 4 +++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/k_collide.cpp b/src/k_collide.cpp index 60a4d02b5..9911895ff 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -796,9 +796,12 @@ boolean K_InstaWhipCollide(mobj_t *t1, mobj_t *t2) { if (t2 != t1->target && !P_PlayerInPain(t2->player) && t2->player->flashing == 0) { + // Damage is a bit hacky, we want only a small loss-of-control + // while still behaving as if it's a "real" hit. P_PlayRinglossSound(t2); P_PlayerRingBurst(t2->player, 5); - P_DamageMobj(t2, t1, t1, 1, DMG_STUMBLE); + P_DamageMobj(t2, t1, t1->target, 1, DMG_STUMBLE); + K_AddHitLag(t2, defenderHitlag, true); K_AddHitLag(t1->target, attackerHitlag, false); t1->hitlag = t1->target->hitlag; @@ -818,12 +821,12 @@ boolean K_InstaWhipCollide(mobj_t *t1, mobj_t *t2) // Damage values in Obj_MonitorGetDamage. if (t2->type == MT_MONITOR) { - if (t1->extravalue1 != 1) + if (t1->extravalue1 == 1) return false; t1->extravalue1 = 1; } - P_DamageMobj(t2, t1, t1, 1, DMG_NORMAL); + P_DamageMobj(t2, t1, t1->target, 1, DMG_NORMAL); K_AddHitLag(t1->target, attackerHitlag, false); t1->hitlag = t1->target->hitlag; } diff --git a/src/p_inter.c b/src/p_inter.c index 620076dd3..6ca9acf66 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2306,7 +2306,9 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da damage = 0; } - if (type == DMG_STING || type == DMG_STUMBLE) + // Instawhip breaks the rules and does "damaging stumble", + // but sting and stumble shouldn't be rewarding Battle hits otherwise. + if ((type == DMG_STING || type == DMG_STUMBLE) && inflictor->type != MT_INSTAWHIP ) { damage = 0; } From dadaab1817789dcfe32fab85dc766b01f73112ea Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 19 May 2023 01:53:14 -0700 Subject: [PATCH 09/29] Add guarding while ebraking with spheres --- src/deh_tables.c | 4 ++ src/info.c | 58 ++++++++++++++++++++++++ src/info.h | 6 +++ src/k_collide.cpp | 92 +++++++++++++++++++++++++++++--------- src/k_collide.h | 2 +- src/k_kart.c | 24 +++++++++- src/k_objects.h | 4 ++ src/objects/CMakeLists.txt | 1 + src/objects/block.c | 68 ++++++++++++++++++++++++++++ src/p_inter.c | 7 ++- src/p_mobj.c | 10 +++++ src/sounds.c | 2 +- 12 files changed, 251 insertions(+), 27 deletions(-) create mode 100644 src/objects/block.c diff --git a/src/deh_tables.c b/src/deh_tables.c index f9ad7fdad..8844cb7b3 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -3288,6 +3288,8 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_SLIPTIDEZIP", "S_INSTAWHIP", + "S_BLOCKRING", + "S_BLOCKBODY", // Signpost sparkles "S_SIGNSPARK1", @@ -5321,6 +5323,8 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_SLIPTIDEZIP", "MT_INSTAWHIP", + "MT_BLOCKRING", + "MT_BLOCKBODY", "MT_SIGNSPARKLE", diff --git a/src/info.c b/src/info.c index 57713644e..7b3f3c177 100644 --- a/src/info.c +++ b/src/info.c @@ -556,6 +556,8 @@ char sprnames[NUMSPRITES + 1][5] = "SLPT", // Sliptide zip indicator "IWHP", // Instawhip + "GRNG", // Guard ring + "GBDY", // Guard body "WIPD", // Wipeout dust trail "DRIF", // Drift Sparks @@ -3949,6 +3951,8 @@ state_t states[NUMSTATES] = {SPR_SLPT, FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_SLIPTIDEZIP {SPR_IWHP, FF_FLOORSPRITE|FF_ANIMATE|0, -1, {NULL}, 6, 2, S_NULL}, // S_INSTAWHIP + {SPR_GRNG, FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_BLOCKRING + {SPR_GBDY, FF_ANIMATE|0, -1, {NULL}, 4, 2, S_NULL}, // S_BLOCKBODY {SPR_SGNS, FF_ADD|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_SIGNSPARK2}, // S_SIGNSPARK1 {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_SIGNSPARK3}, // S_SIGNSPARK2 @@ -22663,6 +22667,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, + + { // MT_BLOCKRING + -1, // doomednum + S_BLOCKRING, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // 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 + 67*FRACUNIT, // radius + 67*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + S_NULL // raisestate + }, + + { // MT_BLOCKBODY + -1, // doomednum + S_BLOCKBODY, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // 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 + 67*FRACUNIT, // radius + 67*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + S_NULL // raisestate + }, { // MT_SIGNSPARKLE -1, // doomednum diff --git a/src/info.h b/src/info.h index 10d35a0a8..af8297eff 100644 --- a/src/info.h +++ b/src/info.h @@ -1109,6 +1109,8 @@ typedef enum sprite SPR_SLPT, // Sliptide zip indicator SPR_IWHP, // Instawhip + SPR_GRNG, // Guard ring + SPR_GBDY, // Guard body SPR_WIPD, // Wipeout dust trail SPR_DRIF, // Drift Sparks @@ -4360,6 +4362,8 @@ typedef enum state S_SLIPTIDEZIP, S_INSTAWHIP, + S_BLOCKRING, + S_BLOCKBODY, // Signpost sparkles S_SIGNSPARK1, @@ -6428,6 +6432,8 @@ typedef enum mobj_type MT_SLIPTIDEZIP, MT_INSTAWHIP, + MT_BLOCKRING, + MT_BLOCKBODY, MT_SIGNSPARKLE, diff --git a/src/k_collide.cpp b/src/k_collide.cpp index 9911895ff..dc34a204d 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -787,48 +787,96 @@ boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2) return true; } -boolean K_InstaWhipCollide(mobj_t *t1, mobj_t *t2) +boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim) { - const int defenderHitlag = 10; + const int victimHitlag = 10; const int attackerHitlag = 4; - if (t2->player) + // EV1 is used to indicate that we should no longer hit monitors. + // EV2 indicates we should no longer hit anything. + if (shield->extravalue2) + return false; + + mobj_t *attacker = shield->target; + + if (!attacker || P_MobjWasRemoved(attacker) || !attacker->player) + return false; // How did we even get here? + + player_t *attackerPlayer = attacker->player; + + if (victim->player) { - if (t2 != t1->target && !P_PlayerInPain(t2->player) && t2->player->flashing == 0) + player_t *victimPlayer = victim->player; + + if (victim != attacker && !P_PlayerInPain(victimPlayer) && victimPlayer->flashing == 0) { + if (K_PlayerEBrake(victimPlayer) && victimPlayer->spheres > 0) + { + if (P_PlayerInPain(attackerPlayer)) + return false; // never punish shield more than once + + angle_t thrangle = R_PointToAngle2(victim->x, victim->y, shield->x, shield->y); + attacker->momx = attacker->momy = 0; + P_Thrust(attacker, thrangle, FRACUNIT*7); + + victimPlayer->spheres = std::min(victimPlayer->spheres + 10, 40); + + shield->renderflags &= ~RF_DONTDRAW; + shield->flags |= MF_NOCLIPTHING; + + attacker->renderflags &= ~RF_DONTDRAW; + attackerPlayer->instaShieldCooldown = TICRATE*2; + attackerPlayer->flashing = 0; + + P_DamageMobj(attacker, victim, victim, 1, DMG_STING); + + S_StartSound(victim, sfx_mbv92); + K_AddHitLag(attacker, 2*victimHitlag, true); + K_AddHitLag(victim, attackerHitlag, false); + attacker->hitlag = std::min(attacker->hitlag, 2*victimHitlag); + shield->hitlag = attacker->hitlag; + + shield->extravalue2 = 1; + + return true; + } + // Damage is a bit hacky, we want only a small loss-of-control // while still behaving as if it's a "real" hit. - P_PlayRinglossSound(t2); - P_PlayerRingBurst(t2->player, 5); - P_DamageMobj(t2, t1, t1->target, 1, DMG_STUMBLE); + P_PlayRinglossSound(victim); + P_PlayerRingBurst(victimPlayer, 5); + P_DamageMobj(victim, shield, attacker, 1, DMG_STUMBLE); // There's a pecial exception in P_DamageMobj for type==MT_INSTAWHIP - K_AddHitLag(t2, defenderHitlag, true); - K_AddHitLag(t1->target, attackerHitlag, false); - t1->hitlag = t1->target->hitlag; + angle_t thrangle = ANGLE_180 + R_PointToAngle2(victim->x, victim->y, shield->x, shield->y); + P_Thrust(victim, thrangle, FRACUNIT*10); + + K_AddHitLag(victim, victimHitlag, true); + K_AddHitLag(attacker, attackerHitlag, false); + shield->hitlag = attacker->hitlag; return true; } return false; } else { - if (t2->type == MT_ORBINAUT || t2->type == MT_JAWZ || t2->type == MT_GACHABOM - || t2->type == MT_BANANA || t2->type == MT_EGGMANITEM || t2->type == MT_BALLHOG - || t2->type == MT_SSMINE || t2->type == MT_LANDMINE || t2->type == MT_SINK - || t2->type == MT_GARDENTOP || t2->type == MT_DROPTARGET || t2->type == MT_BATTLECAPSULE - || t2->type == MT_MONITOR) + if (victim->type == MT_ORBINAUT || victim->type == MT_JAWZ || victim->type == MT_GACHABOM + || victim->type == MT_BANANA || victim->type == MT_EGGMANITEM || victim->type == MT_BALLHOG + || victim->type == MT_SSMINE || victim->type == MT_LANDMINE || victim->type == MT_SINK + || victim->type == MT_GARDENTOP || victim->type == MT_DROPTARGET || victim->type == MT_BATTLECAPSULE + || victim->type == MT_MONITOR) { // Monitor hack. We can hit monitors once per instawhip, no multihit shredding! // Damage values in Obj_MonitorGetDamage. - if (t2->type == MT_MONITOR) + if (victim->type == MT_MONITOR) { - if (t1->extravalue1 == 1) + if (shield->extravalue1 == 1) return false; - t1->extravalue1 = 1; + shield->extravalue1 = 1; } - P_DamageMobj(t2, t1, t1->target, 1, DMG_NORMAL); - K_AddHitLag(t1->target, attackerHitlag, false); - t1->hitlag = t1->target->hitlag; + P_DamageMobj(victim, shield, attacker, 1, DMG_NORMAL); + K_AddHitLag(attacker, attackerHitlag, false); + shield = attacker; } return false; } @@ -1022,7 +1070,7 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2) bool stung = false; - if (t2->player->rings <= 0) + if (t2->player->rings <= 0 && t2->player->spheres <= 0) { P_DamageMobj(t2, t1, t1, 1, DMG_STING|DMG_WOMBO); stung = true; diff --git a/src/k_collide.h b/src/k_collide.h index 0f29ebf6b..84d9a324e 100644 --- a/src/k_collide.h +++ b/src/k_collide.h @@ -24,7 +24,7 @@ boolean K_DropTargetCollide(mobj_t *t1, mobj_t *t2); void K_LightningShieldAttack(mobj_t *actor, fixed_t size); boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2); -boolean K_InstaWhipCollide(mobj_t *t1, mobj_t *t2); +boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim); boolean K_KitchenSinkCollide(mobj_t *t1, mobj_t *t2); diff --git a/src/k_kart.c b/src/k_kart.c index a8d7c207e..4499ca04f 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7777,7 +7777,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) // where's the < 0 check? see below the following block! { - tic_t spheredigestion = TICRATE; // Base rate of 1 every second when playing. + tic_t spheredigestion = TICRATE*2; // Base rate of 1 every second when playing. tic_t digestionpower = ((10 - player->kartspeed) + (10 - player->kartweight))-1; // 1 to 17 // currently 0-34 @@ -7789,7 +7789,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) } else { - spheredigestion -= digestionpower; + spheredigestion -= digestionpower/2; } if ((player->spheres > 0) && (player->spheredigestion > 0)) @@ -7807,6 +7807,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->spheres--; player->spheredigestion = spheredigestion; } + + if (K_PlayerEBrake(player) && (player->ebrakefor%6 == 0)) + player->spheres--; } else { @@ -9833,6 +9836,23 @@ void K_KartEbrakeVisuals(player_t *p) if (!S_SoundPlaying(p->mo, sfx_s3kd9s)) S_ReducedVFXSound(p->mo, sfx_s3kd9s, p); + // Block visuals + // (These objects track whether a player is block-eligible on their own, no worries) + if (!p->ebrakefor) + { + mobj_t *ring = P_SpawnMobj(p->mo->x, p->mo->y, p->mo->z, MT_BLOCKRING); + P_SetTarget(&ring->target, p->mo); + P_SetScale(ring, p->mo->scale); + K_MatchGenericExtraFlags(ring, p->mo); + ring->renderflags &= ~RF_DONTDRAW; + + mobj_t *body = P_SpawnMobj(p->mo->x, p->mo->y, p->mo->z, MT_BLOCKBODY); + P_SetTarget(&body->target, p->mo); + P_SetScale(body, p->mo->scale); + K_MatchGenericExtraFlags(body, p->mo); + body->renderflags |= RF_DONTDRAW; + } + // HOLD! bubble. if (!p->ebrakefor) { diff --git a/src/k_objects.h b/src/k_objects.h index a7788d303..f9f488036 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -110,6 +110,10 @@ boolean Obj_DropTargetMorphThink(mobj_t *morph); /* Instawhip */ void Obj_InstaWhipThink(mobj_t *whip); +/* Block VFX */ +void Obj_BlockRingThink(mobj_t *ring); +void Obj_BlockBodyThink(mobj_t *body); + /* Ring Shooter */ boolean Obj_RingShooterThinker(mobj_t *mo); boolean Obj_PlayerRingShooterFreeze(player_t *const player); diff --git a/src/objects/CMakeLists.txt b/src/objects/CMakeLists.txt index cb2f61519..2fe1f0937 100644 --- a/src/objects/CMakeLists.txt +++ b/src/objects/CMakeLists.txt @@ -18,4 +18,5 @@ target_sources(SRB2SDL2 PRIVATE audience.c random-item.c instawhip.c + block.c ) diff --git a/src/objects/block.c b/src/objects/block.c new file mode 100644 index 000000000..e567473a3 --- /dev/null +++ b/src/objects/block.c @@ -0,0 +1,68 @@ +#include "../doomdef.h" +#include "../info.h" +#include "../k_objects.h" +#include "../p_local.h" + +void Obj_BlockRingThink (mobj_t *ring) +{ + if (P_MobjWasRemoved(ring->target) || !ring->target->player || !ring->target->player->ebrakefor) + { + P_RemoveMobj(ring); + } + else + { + mobj_t *mo = ring->target; + player_t *player = mo->player; + + // Follow player + ring->flags &= ~(MF_NOCLIPTHING); + P_SetScale(ring, mo->scale); + P_MoveOrigin(ring, mo->x, mo->y, mo->z + mo->height/2); + ring->flags |= MF_NOCLIPTHING; + ring->color = mo->color; + + // Twirl + ring->angle = ring->target->angle + (ANG15 * leveltime); + // Visuals + ring->renderflags |= RF_ADD|RF_PAPERSPRITE; + + if (leveltime%2) + ring->renderflags &= ~RF_DONTDRAW; + else + ring->renderflags |= RF_DONTDRAW; + + if (player->spheres == 0) + ring->renderflags |= RF_DONTDRAW; + } +} + +void Obj_BlockBodyThink (mobj_t *body) +{ + if (P_MobjWasRemoved(body->target) || !body->target->player || !body->target->player->ebrakefor) + { + P_RemoveMobj(body); + } + else + { + mobj_t *mo = body->target; + player_t *player = mo->player; + + // Follow player + body->flags &= ~(MF_NOCLIPTHING); + P_SetScale(body, mo->scale); + P_MoveOrigin(body, mo->x, mo->y, mo->z + mo->height/2); + body->flags |= MF_NOCLIPTHING; + body->color = mo->color; + + // Visuals + body->renderflags |= RF_ADD; + + if (leveltime%2 == 0) + body->renderflags &= ~RF_DONTDRAW; + else + body->renderflags |= RF_DONTDRAW; + + if (player->spheres == 0) + body->renderflags |= RF_DONTDRAW; + } +} \ No newline at end of file diff --git a/src/p_inter.c b/src/p_inter.c index 6ca9acf66..1196bd836 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2208,6 +2208,11 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da { sfx = sfx_grownd; } + else if (player->spheres > 0 && K_PlayerEBrake(player)) + { + sfx = sfx_s3k3a; + player->spheres = max(player->spheres - 10, 0); + } else if (player->hyudorotimer > 0) ; else @@ -2308,7 +2313,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da // Instawhip breaks the rules and does "damaging stumble", // but sting and stumble shouldn't be rewarding Battle hits otherwise. - if ((type == DMG_STING || type == DMG_STUMBLE) && inflictor->type != MT_INSTAWHIP ) + if ((type == DMG_STING || type == DMG_STUMBLE) && (inflictor && inflictor->type != MT_INSTAWHIP)) { damage = 0; } diff --git a/src/p_mobj.c b/src/p_mobj.c index 98b9470a8..5f6f6f599 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8361,6 +8361,16 @@ static boolean P_MobjRegularThink(mobj_t *mobj) Obj_InstaWhipThink(mobj); break; } + case MT_BLOCKRING: + { + Obj_BlockRingThink(mobj); + break; + } + case MT_BLOCKBODY: + { + Obj_BlockBodyThink(mobj); + break; + } case MT_GARDENTOPSPARK: { Obj_GardenTopSparkThink(mobj); diff --git a/src/sounds.c b/src/sounds.c index 2f5edb9c6..09d9e437d 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -901,7 +901,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"mbv8f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"mbv90", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"mbv91", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"mbv92", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"mbv92", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Changed falloff for use in instashield parry. {"mbv93", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"mbv94", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"mbv95", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, From df6c9cee730fe98f42807df302f4c385d48fe109 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 19 May 2023 15:34:54 -0700 Subject: [PATCH 10/29] Instashield: actually do height checks --- src/p_map.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/p_map.c b/src/p_map.c index d96afc08d..b72ce2145 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -745,6 +745,10 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) if (tm.thing->type == MT_INSTAWHIP) { + if (tm.thing->z > thing->z + thing->height) + return BMIT_CONTINUE; // overhead + if (tm.thing->z + tm.thing->height < thing->z) + return BMIT_CONTINUE; // underneath K_InstaWhipCollide(tm.thing, thing); return BMIT_CONTINUE; } From a3d954e4ef9ee369b4345fe61612fa6a1c135a33 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 19 May 2023 15:35:31 -0700 Subject: [PATCH 11/29] Guard: Scale graphic to player spheres --- src/objects/block.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/objects/block.c b/src/objects/block.c index e567473a3..ad70ffd6d 100644 --- a/src/objects/block.c +++ b/src/objects/block.c @@ -16,11 +16,14 @@ void Obj_BlockRingThink (mobj_t *ring) // Follow player ring->flags &= ~(MF_NOCLIPTHING); - P_SetScale(ring, mo->scale); P_MoveOrigin(ring, mo->x, mo->y, mo->z + mo->height/2); ring->flags |= MF_NOCLIPTHING; ring->color = mo->color; + fixed_t baseScale = mo->scale / 2; + baseScale += (mo->scale / 30) * player->spheres; + P_SetScale(ring, baseScale); + // Twirl ring->angle = ring->target->angle + (ANG15 * leveltime); // Visuals @@ -49,7 +52,11 @@ void Obj_BlockBodyThink (mobj_t *body) // Follow player body->flags &= ~(MF_NOCLIPTHING); - P_SetScale(body, mo->scale); + + fixed_t baseScale = mo->scale / 2; + baseScale += (mo->scale / 30) * player->spheres; + P_SetScale(body, baseScale); + P_MoveOrigin(body, mo->x, mo->y, mo->z + mo->height/2); body->flags |= MF_NOCLIPTHING; body->color = mo->color; From 6f02923d8917dcea115a11e218750ff8693ee57a Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 19 May 2023 17:59:47 -0700 Subject: [PATCH 12/29] Shield VFX --- src/k_collide.cpp | 26 ++++++++++++++++++++------ src/k_kart.c | 22 ++++++++++++---------- src/k_kart.h | 2 +- src/p_inter.c | 9 ++++++++- src/r_things.c | 2 +- 5 files changed, 42 insertions(+), 19 deletions(-) diff --git a/src/k_collide.cpp b/src/k_collide.cpp index dc34a204d..6528a2c08 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -789,8 +789,8 @@ boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2) boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim) { - const int victimHitlag = 10; - const int attackerHitlag = 4; + int victimHitlag = 10; + int attackerHitlag = 4; // EV1 is used to indicate that we should no longer hit monitors. // EV2 indicates we should no longer hit anything. @@ -810,8 +810,12 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim) if (victim != attacker && !P_PlayerInPain(victimPlayer) && victimPlayer->flashing == 0) { + // BLOW THAT SHIT THE FUCK UP with guard if (K_PlayerEBrake(victimPlayer) && victimPlayer->spheres > 0) + //if (true) { + victimHitlag = 2*victimHitlag; + if (P_PlayerInPain(attackerPlayer)) return false; // never punish shield more than once @@ -825,22 +829,31 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim) shield->flags |= MF_NOCLIPTHING; attacker->renderflags &= ~RF_DONTDRAW; + attackerPlayer->spindashboost = 0; + attackerPlayer->sneakertimer = 0; attackerPlayer->instaShieldCooldown = TICRATE*2; attackerPlayer->flashing = 0; + mobj_t *broly = Obj_SpawnBrolyKi(victim, victimHitlag); + broly->extravalue2 = 16*mapobjectscale; + + P_PlayVictorySound(victim); + P_DamageMobj(attacker, victim, victim, 1, DMG_STING); S_StartSound(victim, sfx_mbv92); - K_AddHitLag(attacker, 2*victimHitlag, true); + K_AddHitLag(attacker, victimHitlag, true); K_AddHitLag(victim, attackerHitlag, false); - attacker->hitlag = std::min(attacker->hitlag, 2*victimHitlag); shield->hitlag = attacker->hitlag; + K_DoPowerClash(shield, victim); + shield->extravalue2 = 1; return true; } + // if you're here, you're getting hit // Damage is a bit hacky, we want only a small loss-of-control // while still behaving as if it's a "real" hit. P_PlayRinglossSound(victim); @@ -967,12 +980,13 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2) || (t1->player->invincibilitytimer > 0) || (t1->player->flamedash > 0 && t1->player->itemtype == KITEM_FLAMESHIELD) || (t1->player->curshield == KSHIELD_TOP && !K_IsHoldingDownTop(t1->player)) - || (t1->player->bubbleblowup > 0); + || (t1->player->bubbleblowup > 0) + || (t1->player->spheres > 0 && K_PlayerEBrake(t1->player)); }; if (canClash(t1, t2) && canClash(t2, t1)) { - K_DoPowerClash(t1->player, t2->player); + K_DoPowerClash(t1, t2); return false; } diff --git a/src/k_kart.c b/src/k_kart.c index 4499ca04f..adc4512a7 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3606,25 +3606,27 @@ void K_DoInstashield(player_t *player) P_SetTarget(&layerb->target, player->mo); } -void K_DoPowerClash(player_t *t1, player_t *t2) { +void K_DoPowerClash(mobj_t *t1, mobj_t *t2) { mobj_t *clash; // short-circuit instashield for vfx visibility - t1->instashield = 1; - t2->instashield = 1; + if (t1->player) + t1->player->instashield = 1; + if (t2->player) + t2->player->instashield = 1; - S_StartSound(t1->mo, sfx_parry); - K_AddHitLag(t1->mo, 6, false); - K_AddHitLag(t2->mo, 6, false); + S_StartSound(t1, sfx_parry); + K_AddHitLag(t1, 6, false); + K_AddHitLag(t2, 6, false); - clash = P_SpawnMobj((t1->mo->x/2) + (t2->mo->x/2), (t1->mo->y/2) + (t2->mo->y/2), (t1->mo->z/2) + (t2->mo->z/2), MT_POWERCLASH); + clash = P_SpawnMobj((t1->x/2) + (t2->x/2), (t1->y/2) + (t2->y/2), (t1->z/2) + (t2->z/2), MT_POWERCLASH); // needs to handle mixed scale collisions (t1 grow t2 invinc)... - clash->z = clash->z + (t1->mo->height/4) + (t2->mo->height/4); - clash->angle = R_PointToAngle2(clash->x, clash->y, t1->mo->x, t1->mo->y) + ANGLE_90; + clash->z = clash->z + (t1->height/4) + (t2->height/4); + clash->angle = R_PointToAngle2(clash->x, clash->y, t1->x, t1->y) + ANGLE_90; // Shrink over time (accidental behavior that looked good) - clash->destscale = (t1->mo->scale/2) + (t2->mo->scale/2); + clash->destscale = (t1->scale) + (t2->scale); P_SetScale(clash, 3*clash->destscale/2); } diff --git a/src/k_kart.h b/src/k_kart.h index 839cadc6c..6bee97b4b 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -90,7 +90,7 @@ void K_AddHitLag(mobj_t *mo, INT32 tics, boolean fromDamage); void K_SetHitLagForObjects(mobj_t *mo1, mobj_t *mo2, INT32 tics, boolean fromDamage); void K_AwardPlayerRings(player_t *player, INT32 rings, boolean overload); void K_DoInstashield(player_t *player); -void K_DoPowerClash(player_t *t1, player_t *t2); +void K_DoPowerClash(mobj_t *t1, mobj_t *t2); void K_BattleAwardHit(player_t *player, player_t *victim, mobj_t *inflictor, UINT8 bumpersRemoved); void K_RemoveGrowShrink(player_t *player); boolean K_IsBigger(mobj_t *compare, mobj_t *other); diff --git a/src/p_inter.c b/src/p_inter.c index 1196bd836..7db485759 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2188,6 +2188,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (!force) { boolean invincible = true; + boolean clash = false; sfxenum_t sfx = sfx_None; if (!(gametyperules & GTR_BUMPERS)) @@ -2211,7 +2212,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da else if (player->spheres > 0 && K_PlayerEBrake(player)) { sfx = sfx_s3k3a; - player->spheres = max(player->spheres - 10, 0); + clash = true; } else if (player->hyudorotimer > 0) ; @@ -2254,6 +2255,12 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da S_StartSound(target, sfx); } + if (clash) + { + player->spheres = max(player->spheres - 10, 0); + K_DoPowerClash(target, inflictor); + } + // Full invulnerability K_DoInstashield(player); return false; diff --git a/src/r_things.c b/src/r_things.c index 337b9c8cf..bc73df96e 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -49,7 +49,7 @@ #include "k_kart.h" // HITLAGJITTERS #include "r_fps.h" -#define MINZ (FRACUNIT*16) +#define MINZ (FRACUNIT*4) #define BASEYCENTER (BASEVIDHEIGHT/2) typedef struct From 9aa4a459ce2052a84e24d363bebc331d41a5c43c Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 19 May 2023 18:45:27 -0700 Subject: [PATCH 13/29] Guard break, UFO instawhip --- src/info.c | 6 +++--- src/k_collide.cpp | 4 ++-- src/k_kart.c | 20 ++++++++++++++++---- src/k_kart.h | 1 + src/objects/block.c | 5 +++-- src/objects/ufo.c | 1 + src/p_inter.c | 2 +- 7 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/info.c b/src/info.c index 7b3f3c177..b75f8cae0 100644 --- a/src/info.c +++ b/src/info.c @@ -3950,9 +3950,9 @@ state_t states[NUMSTATES] = {SPR_SLPT, FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_SLIPTIDEZIP - {SPR_IWHP, FF_FLOORSPRITE|FF_ANIMATE|0, -1, {NULL}, 6, 2, S_NULL}, // S_INSTAWHIP - {SPR_GRNG, FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_BLOCKRING - {SPR_GBDY, FF_ANIMATE|0, -1, {NULL}, 4, 2, S_NULL}, // S_BLOCKBODY + {SPR_IWHP, FF_FULLBRIGHT|FF_FLOORSPRITE|FF_ANIMATE|0, -1, {NULL}, 6, 2, S_NULL}, // S_INSTAWHIP + {SPR_GRNG, FF_FULLBRIGHT|FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_BLOCKRING + {SPR_GBDY, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 2, S_NULL}, // S_BLOCKBODY {SPR_SGNS, FF_ADD|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_SIGNSPARK2}, // S_SIGNSPARK1 {SPR_SGNS, FF_ADD|FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_SIGNSPARK3}, // S_SIGNSPARK2 diff --git a/src/k_collide.cpp b/src/k_collide.cpp index 6528a2c08..af5e79d48 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -811,7 +811,7 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim) if (victim != attacker && !P_PlayerInPain(victimPlayer) && victimPlayer->flashing == 0) { // BLOW THAT SHIT THE FUCK UP with guard - if (K_PlayerEBrake(victimPlayer) && victimPlayer->spheres > 0) + if (K_PlayerGuard(victimPlayer)) //if (true) { victimHitlag = 2*victimHitlag; @@ -876,7 +876,7 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim) || victim->type == MT_BANANA || victim->type == MT_EGGMANITEM || victim->type == MT_BALLHOG || victim->type == MT_SSMINE || victim->type == MT_LANDMINE || victim->type == MT_SINK || victim->type == MT_GARDENTOP || victim->type == MT_DROPTARGET || victim->type == MT_BATTLECAPSULE - || victim->type == MT_MONITOR) + || victim->type == MT_MONITOR || victim->type == MT_SPECIAL_UFO) { // Monitor hack. We can hit monitors once per instawhip, no multihit shredding! // Damage values in Obj_MonitorGetDamage. diff --git a/src/k_kart.c b/src/k_kart.c index adc4512a7..f71700098 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -718,7 +718,7 @@ static void K_SpawnBumpForObjs(mobj_t *mobj1, mobj_t *mobj2) } } -static void K_PlayerJustBumped(player_t *player) +static void K_PlayerJustBumped(player_t *player, boolean guardbreak) { mobj_t *playerMobj = NULL; @@ -742,6 +742,13 @@ static void K_PlayerJustBumped(player_t *player) player->rmomy = playerMobj->momy - player->cmomy; } + if (guardbreak && K_PlayerGuard(player)) + { + S_StartSound(player->mo, sfx_s3k9e); + K_AddHitLag(player->mo, TICRATE, true); + player->instaShieldCooldown = 2*TICRATE; + } + player->justbumped = bumptime; player->spindash = 0; @@ -933,8 +940,8 @@ boolean K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2) K_SpawnBumpForObjs(mobj1, mobj2); - K_PlayerJustBumped(mobj1->player); - K_PlayerJustBumped(mobj2->player); + K_PlayerJustBumped(mobj1->player, true); + K_PlayerJustBumped(mobj2->player, true); return true; } @@ -1003,7 +1010,7 @@ boolean K_KartSolidBounce(mobj_t *bounceMobj, mobj_t *solidMobj) bounceMobj->momz = -bounceMobj->momz; K_SpawnBumpForObjs(bounceMobj, solidMobj); - K_PlayerJustBumped(bounceMobj->player); + K_PlayerJustBumped(bounceMobj->player, false); return true; } @@ -9797,6 +9804,11 @@ boolean K_PlayerEBrake(player_t *player) return false; } +boolean K_PlayerGuard(player_t *player) +{ + return (K_PlayerEBrake(player) && player->spheres > 0 && player->instaShieldCooldown == 0); +} + SINT8 K_Sliptiding(player_t *player) { if (player->mo->eflags & MFE_UNDERWATER) diff --git a/src/k_kart.h b/src/k_kart.h index 6bee97b4b..46f530900 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -178,6 +178,7 @@ SINT8 K_GetForwardMove(player_t *player); fixed_t K_GetNewSpeed(player_t *player); fixed_t K_3dKartMovement(player_t *player); boolean K_PlayerEBrake(player_t *player); +boolean K_PlayerGuard(player_t *player); SINT8 K_Sliptiding(player_t *player); boolean K_FastFallBounce(player_t *player); fixed_t K_PlayerBaseFriction(player_t *player, fixed_t original); diff --git a/src/objects/block.c b/src/objects/block.c index ad70ffd6d..bf54f908a 100644 --- a/src/objects/block.c +++ b/src/objects/block.c @@ -2,6 +2,7 @@ #include "../info.h" #include "../k_objects.h" #include "../p_local.h" +#include "../k_kart.h" void Obj_BlockRingThink (mobj_t *ring) { @@ -34,7 +35,7 @@ void Obj_BlockRingThink (mobj_t *ring) else ring->renderflags |= RF_DONTDRAW; - if (player->spheres == 0) + if (!K_PlayerGuard(player)) ring->renderflags |= RF_DONTDRAW; } } @@ -69,7 +70,7 @@ void Obj_BlockBodyThink (mobj_t *body) else body->renderflags |= RF_DONTDRAW; - if (player->spheres == 0) + if (!K_PlayerGuard(player)) body->renderflags |= RF_DONTDRAW; } } \ No newline at end of file diff --git a/src/objects/ufo.c b/src/objects/ufo.c index 7d8b2ea8e..7a4cf56c0 100644 --- a/src/objects/ufo.c +++ b/src/objects/ufo.c @@ -670,6 +670,7 @@ static UINT8 GetUFODamage(mobj_t *inflictor, UINT8 damageType) { case MT_JAWZ_SHIELD: case MT_ORBINAUT_SHIELD: + case MT_INSTAWHIP: { // Shields deal chip damage. return 10; diff --git a/src/p_inter.c b/src/p_inter.c index 7db485759..b598e9365 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2209,7 +2209,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da { sfx = sfx_grownd; } - else if (player->spheres > 0 && K_PlayerEBrake(player)) + else if (K_PlayerGuard(player)) { sfx = sfx_s3k3a; clash = true; From d725963f42db4976ff201b74cfb99688af19e252 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 19 May 2023 18:56:14 -0700 Subject: [PATCH 14/29] Don't drain spheres while ebraking in guardbreak --- src/k_kart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index f71700098..de98f8378 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7817,7 +7817,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->spheredigestion = spheredigestion; } - if (K_PlayerEBrake(player) && (player->ebrakefor%6 == 0)) + if (K_PlayerGuard(player) && (player->ebrakefor%6 == 0)) player->spheres--; } else @@ -10588,7 +10588,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) K_MatchGenericExtraFlags(whip, player->mo); whip->fuse = 12; // Changing instawhip animation duration? Look here player->flashing = max(player->flashing, 12); - player->mo->momz += FRACUNIT; + player->mo->momz += 4*mapobjectscale; } } From f6407d03d024925113ea07c2cf975c1eb0b5d909 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 19 May 2023 19:45:20 -0700 Subject: [PATCH 15/29] More guard sfx --- src/k_kart.c | 5 ++++- src/sounds.c | 3 ++- src/sounds.h | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index de98f8378..d04b71171 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -744,7 +744,7 @@ static void K_PlayerJustBumped(player_t *player, boolean guardbreak) if (guardbreak && K_PlayerGuard(player)) { - S_StartSound(player->mo, sfx_s3k9e); + S_StartSound(player->mo, sfx_gbrk); K_AddHitLag(player->mo, TICRATE, true); player->instaShieldCooldown = 2*TICRATE; } @@ -9865,6 +9865,9 @@ void K_KartEbrakeVisuals(player_t *p) P_SetScale(body, p->mo->scale); K_MatchGenericExtraFlags(body, p->mo); body->renderflags |= RF_DONTDRAW; + + if (K_PlayerGuard(p)) + S_StartSound(body, sfx_s1af); } // HOLD! bubble. diff --git a/src/sounds.c b/src/sounds.c index 09d9e437d..d8852928b 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -1184,7 +1184,8 @@ sfxinfo_t S_sfx[NUMSFX] = {"monch", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"etexpl", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Game crash"}, - {"iwhp", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Grow alarm + {"iwhp", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Instawhip attack + {"gbrk", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Guard break! // SRB2Kart - Engine sounds // Engine class A diff --git a/src/sounds.h b/src/sounds.h index fda612893..422138d65 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -1254,6 +1254,7 @@ typedef enum sfx_etexpl, sfx_iwhp, + sfx_gbrk, // Next up: UNIQUE ENGINE SOUNDS! Hoooooo boy... // Engine class A - Low Speed, Low Weight From bfcc453d5698cec1d1305d33127bb1f0ed084ac8 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 19 May 2023 21:14:47 -0700 Subject: [PATCH 16/29] Guard Break FX --- src/deh_tables.c | 4 +++- src/info.c | 29 ++++++++++++++++++++++++++++ src/info.h | 3 +++ src/k_kart.c | 47 ++++++++++++++++++++++++++++++++++----------- src/k_kart.h | 1 + src/k_objects.h | 1 + src/objects/block.c | 8 ++++++++ src/p_mobj.c | 5 +++++ 8 files changed, 86 insertions(+), 12 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index 8844cb7b3..d348b3a4a 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4015,6 +4015,7 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_INSTASHIELDB7", "S_POWERCLASH", // Invinc/Grow no damage collide VFX + "S_GUARDBREAK", // Guard break "S_PLAYERARROW", // Above player arrow "S_PLAYERARROW_BOX", @@ -5495,7 +5496,8 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_INSTASHIELDB", "MT_POWERCLASH", // Invinc/Grow no damage clash VFX - + "MT_GUARDBREAK", // Guard break + "MT_PLAYERARROW", "MT_PLAYERWANTED", diff --git a/src/info.c b/src/info.c index b75f8cae0..74b9c70db 100644 --- a/src/info.c +++ b/src/info.c @@ -638,6 +638,7 @@ char sprnames[NUMSPRITES + 1][5] = "ISTB", // instashield layer B "PWCL", // Invinc/grow clash VFX + "GBRK", // Guard break "ARRO", // player arrows "ITEM", @@ -4635,6 +4636,7 @@ state_t states[NUMSTATES] = {SPR_ISTB, FF_FULLBRIGHT|6, 2, {NULL}, 0, 0, S_NULL}, // S_INSTASHIELDB7 {SPR_PWCL, FF_FULLBRIGHT|FF_ANIMATE|FF_PAPERSPRITE, 10, {NULL}, 9, 1, S_NULL}, // S_POWERCLASH + {SPR_GBRK, FF_ADD|FF_FULLBRIGHT|FF_ANIMATE|FF_PAPERSPRITE, 24, {NULL}, 5, 4, S_NULL}, // S_GUARDBREAK // Above player arrow {SPR_ARRO, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW @@ -26178,6 +26180,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_GUARDBREAK + -1, // doomednum + S_GUARDBREAK, // 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 + 8*FRACUNIT, // radius + 8*FRACUNIT, // height + 2, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags + S_NULL // raisestate + }, + { // MT_PLAYERARROW -1, // doomednum S_PLAYERARROW, // spawnstate diff --git a/src/info.h b/src/info.h index af8297eff..c2d7a0356 100644 --- a/src/info.h +++ b/src/info.h @@ -1191,6 +1191,7 @@ typedef enum sprite SPR_ISTB, // instashield layer B SPR_PWCL, // Invinc/grow clash VFX + SPR_GBRK, // Guard break SPR_ARRO, // player arrows SPR_ITEM, @@ -5088,6 +5089,7 @@ typedef enum state S_INSTASHIELDB7, S_POWERCLASH, // Grow/Invinc clash VFX + S_GUARDBREAK, S_PLAYERARROW, // Above player arrow S_PLAYERARROW_BOX, @@ -6604,6 +6606,7 @@ typedef enum mobj_type MT_INSTASHIELDB, MT_POWERCLASH, // Grow/Invinc clash VFX + MT_GUARDBREAK, MT_PLAYERARROW, MT_PLAYERWANTED, diff --git a/src/k_kart.c b/src/k_kart.c index d04b71171..a1fba70ab 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -718,7 +718,7 @@ static void K_SpawnBumpForObjs(mobj_t *mobj1, mobj_t *mobj2) } } -static void K_PlayerJustBumped(player_t *player, boolean guardbreak) +static void K_PlayerJustBumped(player_t *player) { mobj_t *playerMobj = NULL; @@ -742,13 +742,6 @@ static void K_PlayerJustBumped(player_t *player, boolean guardbreak) player->rmomy = playerMobj->momy - player->cmomy; } - if (guardbreak && K_PlayerGuard(player)) - { - S_StartSound(player->mo, sfx_gbrk); - K_AddHitLag(player->mo, TICRATE, true); - player->instaShieldCooldown = 2*TICRATE; - } - player->justbumped = bumptime; player->spindash = 0; @@ -940,8 +933,16 @@ boolean K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2) K_SpawnBumpForObjs(mobj1, mobj2); - K_PlayerJustBumped(mobj1->player, true); - K_PlayerJustBumped(mobj2->player, true); + if (mobj1->type == MT_PLAYER && mobj2->type == MT_PLAYER) + { + if (K_PlayerGuard(mobj1->player)) + K_DoGuardBreak(mobj1, mobj2); + if (K_PlayerGuard(mobj2->player)) + K_DoGuardBreak(mobj2, mobj1); + } + + K_PlayerJustBumped(mobj1->player); + K_PlayerJustBumped(mobj2->player); return true; } @@ -1010,7 +1011,7 @@ boolean K_KartSolidBounce(mobj_t *bounceMobj, mobj_t *solidMobj) bounceMobj->momz = -bounceMobj->momz; K_SpawnBumpForObjs(bounceMobj, solidMobj); - K_PlayerJustBumped(bounceMobj->player, false); + K_PlayerJustBumped(bounceMobj->player); return true; } @@ -1986,6 +1987,7 @@ void K_SpawnMagicianParticles(mobj_t *mo, int spread) dust->frame |= FF_SUBTRACT|FF_TRANS90; dust->color = color; dust->colorized = true; + dust->hitlag = 0; } } @@ -3637,6 +3639,29 @@ void K_DoPowerClash(mobj_t *t1, mobj_t *t2) { P_SetScale(clash, 3*clash->destscale/2); } +void K_DoGuardBreak(mobj_t *t1, mobj_t *t2) { + mobj_t *clash; + + if (!(t1->player && t2->player)) + return; + + // short-circuit instashield for vfx visibility + t1->player->instaShieldCooldown = 2*TICRATE; + + S_StartSound(t1, sfx_gbrk); + K_AddHitLag(t1, 24, true); + P_DamageMobj(t1, t2, t2, 1, DMG_STING); + + clash = P_SpawnMobj((t1->x/2) + (t2->x/2), (t1->y/2) + (t2->y/2), (t1->z/2) + (t2->z/2), MT_GUARDBREAK); + + // needs to handle mixed scale collisions + clash->z = clash->z + (t1->height/4) + (t2->height/4); + clash->angle = R_PointToAngle2(clash->x, clash->y, t1->x, t1->y) + ANGLE_90; + clash->color = t1->color; + + clash->destscale = 3*((t1->scale) + (t2->scale))/2; +} + void K_BattleAwardHit(player_t *player, player_t *victim, mobj_t *inflictor, UINT8 damage) { UINT8 points = 1; diff --git a/src/k_kart.h b/src/k_kart.h index 46f530900..a12388af8 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -91,6 +91,7 @@ void K_SetHitLagForObjects(mobj_t *mo1, mobj_t *mo2, INT32 tics, boolean fromDam void K_AwardPlayerRings(player_t *player, INT32 rings, boolean overload); void K_DoInstashield(player_t *player); void K_DoPowerClash(mobj_t *t1, mobj_t *t2); +void K_DoGuardBreak(mobj_t *t1, mobj_t *t2); void K_BattleAwardHit(player_t *player, player_t *victim, mobj_t *inflictor, UINT8 bumpersRemoved); void K_RemoveGrowShrink(player_t *player); boolean K_IsBigger(mobj_t *compare, mobj_t *other); diff --git a/src/k_objects.h b/src/k_objects.h index f9f488036..07a906a84 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -113,6 +113,7 @@ void Obj_InstaWhipThink(mobj_t *whip); /* Block VFX */ void Obj_BlockRingThink(mobj_t *ring); void Obj_BlockBodyThink(mobj_t *body); +void Obj_GuardBreakThink(mobj_t *fx); /* Ring Shooter */ boolean Obj_RingShooterThinker(mobj_t *mo); diff --git a/src/objects/block.c b/src/objects/block.c index bf54f908a..1d715ecbe 100644 --- a/src/objects/block.c +++ b/src/objects/block.c @@ -73,4 +73,12 @@ void Obj_BlockBodyThink (mobj_t *body) if (!K_PlayerGuard(player)) body->renderflags |= RF_DONTDRAW; } +} + +void Obj_GuardBreakThink (mobj_t *fx) +{ + if (leveltime%2) + fx->renderflags &= ~RF_DONTDRAW; + else + fx->renderflags |= RF_DONTDRAW; } \ No newline at end of file diff --git a/src/p_mobj.c b/src/p_mobj.c index 5f6f6f599..dcedd4105 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8371,6 +8371,11 @@ static boolean P_MobjRegularThink(mobj_t *mobj) Obj_BlockBodyThink(mobj); break; } + case MT_GUARDBREAK: + { + Obj_GuardBreakThink(mobj); + break; + } case MT_GARDENTOPSPARK: { Obj_GardenTopSparkThink(mobj); From cac02bb01ab7d8913e5a031c996f46c7b96b5128 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 19 May 2023 22:51:06 -0700 Subject: [PATCH 17/29] Emerald fixups --- src/k_battle.c | 5 +++-- src/k_kart.c | 2 +- src/objects/monitor.c | 14 +++++++++++++- src/p_inter.c | 5 ++++- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/k_battle.c b/src/k_battle.c index 7d2ad8039..d7997a809 100644 --- a/src/k_battle.c +++ b/src/k_battle.c @@ -197,9 +197,9 @@ mobj_t *K_SpawnChaosEmerald(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT P_Thrust(emerald, FixedAngle(P_RandomFixed(PR_ITEM_ROULETTE) * 180) + angle, - 24 * mapobjectscale); + 36 * mapobjectscale); - emerald->momz = flip * 24 * mapobjectscale; + emerald->momz = flip * 36 * mapobjectscale; if (emerald->eflags & MFE_UNDERWATER) emerald->momz = (117 * emerald->momz) / 200; @@ -275,6 +275,7 @@ void K_DropEmeraldsFromPlayer(player_t *player, UINT32 emeraldType) P_SetTarget(&emerald->target, player->mo); player->emeralds &= ~emeraldFlag; + break; // Drop only one emerald. Emerald wins are hard enough! } } } diff --git a/src/k_kart.c b/src/k_kart.c index a1fba70ab..075a57dbc 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -11923,7 +11923,7 @@ UINT32 K_PointLimitForGametype(void) { if (D_IsPlayerHumanAndGaming(i)) { - ptsCap += 3; + ptsCap += 5; } } } diff --git a/src/objects/monitor.c b/src/objects/monitor.c index fccb1a0f9..683ad11de 100644 --- a/src/objects/monitor.c +++ b/src/objects/monitor.c @@ -440,7 +440,13 @@ adjust_monitor_drop ( mobj_t * monitor, mobj_t * drop) { - P_InstaThrust(drop, drop->angle, 4*mapobjectscale); + if (drop->type == MT_EMERALD) + { + drop->momz = 0; + drop->angle = 0; + } + + P_InstaThrust(drop, drop->angle, 8*mapobjectscale); drop->momz *= 8; @@ -616,9 +622,15 @@ Obj_MonitorGetDamage else { if (inflictor->type == MT_INSTAWHIP) + { damage = FRACUNIT/3; + if (K_IsPlayerWanted(inflictor->target->player)) + damage = FRACUNIT; // Emerald hunting time! + } else + { damage = FRACUNIT; // kill instantly + } } return damage; diff --git a/src/p_inter.c b/src/p_inter.c index b598e9365..21dcd9779 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2258,7 +2258,10 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (clash) { player->spheres = max(player->spheres - 10, 0); - K_DoPowerClash(target, inflictor); + if (inflictor) + K_DoPowerClash(target, inflictor); + else if (source) + K_DoPowerClash(target, source); } // Full invulnerability From de8f4812cf583ed2c0cd18cfdb451451acbdcd8e Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 19 May 2023 23:30:20 -0700 Subject: [PATCH 18/29] Split instashield and guard cooldown --- src/d_player.h | 1 + src/k_collide.cpp | 1 + src/k_kart.c | 10 +++++++++- src/lua_playerlib.c | 4 ++++ src/p_saveg.c | 2 ++ 5 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/d_player.h b/src/d_player.h index 10a8c02e5..5930cdede 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -743,6 +743,7 @@ struct player_t mobj_t *sliptideZipIndicator; UINT8 instaShieldCooldown; + UINT8 guardCooldown; uint8_t public_key[PUBKEYLENGTH]; diff --git a/src/k_collide.cpp b/src/k_collide.cpp index af5e79d48..300db8f50 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -832,6 +832,7 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim) attackerPlayer->spindashboost = 0; attackerPlayer->sneakertimer = 0; attackerPlayer->instaShieldCooldown = TICRATE*2; + attackerPlayer->guardCooldown = TICRATE*2; attackerPlayer->flashing = 0; mobj_t *broly = Obj_SpawnBrolyKi(victim, victimHitlag); diff --git a/src/k_kart.c b/src/k_kart.c index 075a57dbc..f9a32344d 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3647,6 +3647,7 @@ void K_DoGuardBreak(mobj_t *t1, mobj_t *t2) { // short-circuit instashield for vfx visibility t1->player->instaShieldCooldown = 2*TICRATE; + t1->player->guardCooldown = 2*TICRATE; S_StartSound(t1, sfx_gbrk); K_AddHitLag(t1, 24, true); @@ -7920,6 +7921,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (!P_IsObjectOnGround(player->mo)) player->instaShieldCooldown = max(player->instaShieldCooldown, 1); } + + if (player->guardCooldown) + player->guardCooldown--; if (player->startboost > 0 && onground == true) @@ -8142,6 +8146,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->pflags &= ~PF_DRIFTINPUT; } + if (K_PlayerGuard(player)) + player->instaShieldCooldown = max(player->instaShieldCooldown, 12); + // Roulette Code K_KartItemRoulette(player, cmd); @@ -9831,7 +9838,7 @@ boolean K_PlayerEBrake(player_t *player) boolean K_PlayerGuard(player_t *player) { - return (K_PlayerEBrake(player) && player->spheres > 0 && player->instaShieldCooldown == 0); + return (K_PlayerEBrake(player) && player->spheres > 0 && player->guardCooldown == 0); } SINT8 K_Sliptiding(player_t *player) @@ -10609,6 +10616,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) else { player->instaShieldCooldown = 50; + player->guardCooldown = 50; S_StartSound(player->mo, sfx_iwhp); mobj_t *whip = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_INSTAWHIP); P_SetScale(whip, player->mo->scale); diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 39039e011..60f7959b5 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -321,6 +321,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->sliptideZipBoost); else if (fastcmp(field,"instaShieldCooldown")) lua_pushinteger(L, plr->instaShieldCooldown); + else if (fastcmp(field,"guardCooldown")) + lua_pushinteger(L, plr->guardCooldown); /* else if (fastcmp(field,"itemroulette")) lua_pushinteger(L, plr->itemroulette); @@ -717,6 +719,8 @@ static int player_set(lua_State *L) plr->sliptideZipBoost = luaL_checkinteger(L, 3); else if (fastcmp(field,"instaShieldCooldown")) plr->instaShieldCooldown = luaL_checkinteger(L, 3); + else if (fastcmp(field,"guardCooldown")) + plr->guardCooldown = luaL_checkinteger(L, 3); /* else if (fastcmp(field,"itemroulette")) plr->itemroulette = luaL_checkinteger(L, 3); diff --git a/src/p_saveg.c b/src/p_saveg.c index 46cf3afeb..3b821e990 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -420,6 +420,7 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEMEM(save->p, players[i].public_key, PUBKEYLENGTH); WRITEUINT8(save->p, players[i].instaShieldCooldown); + WRITEUINT8(save->p, players[i].guardCooldown); // respawnvars_t WRITEUINT8(save->p, players[i].respawn.state); @@ -807,6 +808,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) READMEM(save->p, players[i].public_key, PUBKEYLENGTH); players[i].instaShieldCooldown = READUINT8(save->p); + players[i].guardCooldown = READUINT8(save->p); // respawnvars_t players[i].respawn.state = READUINT8(save->p); From 2c44bafe746d2d7d0221cc5636944c90241a57cd Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 19 May 2023 23:43:53 -0700 Subject: [PATCH 19/29] Misc fixup --- src/k_collide.cpp | 10 ++++++---- src/p_inter.c | 3 +++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/k_collide.cpp b/src/k_collide.cpp index 300db8f50..96aeecce6 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -811,10 +811,10 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim) if (victim != attacker && !P_PlayerInPain(victimPlayer) && victimPlayer->flashing == 0) { // BLOW THAT SHIT THE FUCK UP with guard - if (K_PlayerGuard(victimPlayer)) - //if (true) + //if (K_PlayerGuard(victimPlayer)) + if (true) { - victimHitlag = 2*victimHitlag; + victimHitlag = 3*victimHitlag; if (P_PlayerInPain(attackerPlayer)) return false; // never punish shield more than once @@ -845,10 +845,12 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim) S_StartSound(victim, sfx_mbv92); K_AddHitLag(attacker, victimHitlag, true); K_AddHitLag(victim, attackerHitlag, false); - shield->hitlag = attacker->hitlag; K_DoPowerClash(shield, victim); + attacker->hitlag = victimHitlag; // No, seriously, we do not care about K_AddHitLag's idea of a normal maximum + shield->hitlag = attacker->hitlag; + shield->extravalue2 = 1; return true; diff --git a/src/p_inter.c b/src/p_inter.c index 21dcd9779..cf8333dfb 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2443,6 +2443,9 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da K_PlayPainSound(target, source); } + if (gametyperules & GTR_BUMPERS) + player->spheres = min(player->spheres + 5, 40); + if ((hardhit == true) || cv_kartdebughuddrop.value) { K_DropItems(player); From 53a2a999d2403dca0046672cbd7ad16441caa59a Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 19 May 2023 23:45:52 -0700 Subject: [PATCH 20/29] Whoops, that's a testing condition --- src/k_collide.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_collide.cpp b/src/k_collide.cpp index 96aeecce6..bc40fa66f 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -811,8 +811,8 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim) if (victim != attacker && !P_PlayerInPain(victimPlayer) && victimPlayer->flashing == 0) { // BLOW THAT SHIT THE FUCK UP with guard - //if (K_PlayerGuard(victimPlayer)) - if (true) + if (K_PlayerGuard(victimPlayer)) + //if (true) { victimHitlag = 3*victimHitlag; From 211e28611b168157dd2d8731a0b8494eaeae1d31 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sat, 20 May 2023 00:15:05 -0700 Subject: [PATCH 21/29] Instawhip: No mercy --- src/k_collide.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/k_collide.cpp b/src/k_collide.cpp index bc40fa66f..e8a088d8c 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -808,7 +808,8 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim) { player_t *victimPlayer = victim->player; - if (victim != attacker && !P_PlayerInPain(victimPlayer) && victimPlayer->flashing == 0) + //if (victim != attacker && !P_PlayerInPain(victimPlayer) && victimPlayer->flashing == 0) + if (victim != attacker && victim->hitlag == 0) { // BLOW THAT SHIT THE FUCK UP with guard if (K_PlayerGuard(victimPlayer)) From 3b947ebf85a56777691a45ab7dc19a497d8c1de6 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sat, 20 May 2023 02:39:05 -0700 Subject: [PATCH 22/29] Instawhip: On mutual contact, clash! --- src/d_player.h | 1 + src/g_game.c | 1 + src/k_collide.cpp | 28 +++++++++++++++++++++++++--- src/k_kart.c | 3 +++ src/p_saveg.c | 19 ++++++++++++++++++- 5 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 5930cdede..2e7aeae1b 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -741,6 +741,7 @@ struct player_t mobj_t *stumbleIndicator; mobj_t *sliptideZipIndicator; + mobj_t *whip; UINT8 instaShieldCooldown; UINT8 guardCooldown; diff --git a/src/g_game.c b/src/g_game.c index 37399c561..9f75d137a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2675,6 +2675,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) P_SetTarget(&players[player].follower, NULL); P_SetTarget(&players[player].awayview.mobj, NULL); P_SetTarget(&players[player].stumbleIndicator, NULL); + P_SetTarget(&players[player].whip, NULL); P_SetTarget(&players[player].ringShooter, NULL); P_SetTarget(&players[player].followmobj, NULL); diff --git a/src/k_collide.cpp b/src/k_collide.cpp index e8a088d8c..d2b886048 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -811,7 +811,26 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim) //if (victim != attacker && !P_PlayerInPain(victimPlayer) && victimPlayer->flashing == 0) if (victim != attacker && victim->hitlag == 0) { - // BLOW THAT SHIT THE FUCK UP with guard + // If both players have a whip, hits are order-of-execution dependent and that sucks. + // Player expectation is a clash here. + if (victimPlayer->whip && !P_MobjWasRemoved(victimPlayer->whip)) + { + victimPlayer->whip->extravalue2 = 1; + shield->extravalue2 = 1; + + K_DoPowerClash(victim, attacker); + + victim->renderflags &= ~RF_DONTDRAW; + attacker->renderflags &= ~RF_DONTDRAW; + + angle_t thrangle = R_PointToAngle2(attacker->x, attacker->y, victim->x, victim->y); + P_Thrust(victim, thrangle, FRACUNIT*7); + P_Thrust(attacker, ANGLE_180 + thrangle, FRACUNIT*7); + + return false; + } + + // Instawhip _always_ loses to guard. if (K_PlayerGuard(victimPlayer)) //if (true) { @@ -824,11 +843,13 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim) attacker->momx = attacker->momy = 0; P_Thrust(attacker, thrangle, FRACUNIT*7); + // A little extra juice, so successful reads are usually positive or zero on spheres. victimPlayer->spheres = std::min(victimPlayer->spheres + 10, 40); shield->renderflags &= ~RF_DONTDRAW; shield->flags |= MF_NOCLIPTHING; + // Attacker should be free to all reasonable followups. attacker->renderflags &= ~RF_DONTDRAW; attackerPlayer->spindashboost = 0; attackerPlayer->sneakertimer = 0; @@ -836,6 +857,7 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim) attackerPlayer->guardCooldown = TICRATE*2; attackerPlayer->flashing = 0; + // Localized broly for a local event. mobj_t *broly = Obj_SpawnBrolyKi(victim, victimHitlag); broly->extravalue2 = 16*mapobjectscale; @@ -847,7 +869,7 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim) K_AddHitLag(attacker, victimHitlag, true); K_AddHitLag(victim, attackerHitlag, false); - K_DoPowerClash(shield, victim); + K_DoPowerClash(shield, victim); // REJECTED attacker->hitlag = victimHitlag; // No, seriously, we do not care about K_AddHitLag's idea of a normal maximum shield->hitlag = attacker->hitlag; @@ -862,7 +884,7 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim) // while still behaving as if it's a "real" hit. P_PlayRinglossSound(victim); P_PlayerRingBurst(victimPlayer, 5); - P_DamageMobj(victim, shield, attacker, 1, DMG_STUMBLE); // There's a pecial exception in P_DamageMobj for type==MT_INSTAWHIP + P_DamageMobj(victim, shield, attacker, 1, DMG_STUMBLE); // There's a special exception in P_DamageMobj for type==MT_INSTAWHIP angle_t thrangle = ANGLE_180 + R_PointToAngle2(victim->x, victim->y, shield->x, shield->y); P_Thrust(victim, thrangle, FRACUNIT*10); diff --git a/src/k_kart.c b/src/k_kart.c index f9a32344d..6cd6a0d76 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7925,6 +7925,8 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->guardCooldown) player->guardCooldown--; + if (player->whip && P_MobjWasRemoved(player->whip)) + player->whip = NULL; if (player->startboost > 0 && onground == true) { @@ -10619,6 +10621,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->guardCooldown = 50; S_StartSound(player->mo, sfx_iwhp); mobj_t *whip = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_INSTAWHIP); + player->whip = whip; P_SetScale(whip, player->mo->scale); P_SetTarget(&whip->target, player->mo); K_MatchGenericExtraFlags(whip, player->mo); diff --git a/src/p_saveg.c b/src/p_saveg.c index 3b821e990..013d81830 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -74,7 +74,8 @@ typedef enum HOVERHYUDORO = 0x0020, STUMBLE = 0x0040, SLIPTIDEZIP = 0x0080, - RINGSHOOTER = 0x0100 + RINGSHOOTER = 0x0100, + WHIP = 0x0200, } player_saveflags; static inline void P_ArchivePlayer(savebuffer_t *save) @@ -225,6 +226,9 @@ static void P_NetArchivePlayers(savebuffer_t *save) if (players[i].sliptideZipIndicator) flags |= SLIPTIDEZIP; + if (players[i].whip) + flags |= WHIP; + if (players[i].ringShooter) flags |= RINGSHOOTER; @@ -251,6 +255,9 @@ static void P_NetArchivePlayers(savebuffer_t *save) if (flags & SLIPTIDEZIP) WRITEUINT32(save->p, players[i].sliptideZipIndicator->mobjnum); + if (flags & WHIP) + WRITEUINT32(save->p, players[i].whip->mobjnum); + if (flags & RINGSHOOTER) WRITEUINT32(save->p, players[i].ringShooter->mobjnum); @@ -638,6 +645,9 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) if (flags & SLIPTIDEZIP) players[i].sliptideZipIndicator = (mobj_t *)(size_t)READUINT32(save->p); + if (flags & WHIP) + players[i].whip = (mobj_t *)(size_t)READUINT32(save->p); + if (flags & RINGSHOOTER) players[i].ringShooter = (mobj_t *)(size_t)READUINT32(save->p); @@ -4987,6 +4997,13 @@ static void P_RelinkPointers(void) if (!P_SetTarget(&players[i].sliptideZipIndicator, P_FindNewPosition(temp))) CONS_Debug(DBG_GAMELOGIC, "sliptideZipIndicator not found on player %d\n", i); } + if (players[i].whip) + { + temp = (UINT32)(size_t)players[i].whip; + players[i].whip = NULL; + if (!P_SetTarget(&players[i].whip, P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "whip not found on player %d\n", i); + } if (players[i].ringShooter) { temp = (UINT32)(size_t)players[i].ringShooter; From 85bfd5be1298d2aca1111c04ae30d8b4990a4bac Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sat, 20 May 2023 02:53:13 -0700 Subject: [PATCH 23/29] Really, really drop emeralds from monitors dead center on the ground --- src/objects/monitor.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/objects/monitor.c b/src/objects/monitor.c index 683ad11de..072cfbe84 100644 --- a/src/objects/monitor.c +++ b/src/objects/monitor.c @@ -442,13 +442,13 @@ adjust_monitor_drop { if (drop->type == MT_EMERALD) { - drop->momz = 0; - drop->angle = 0; + drop->momx = drop->momy = drop->momz = 0; + } + else + { + P_InstaThrust(drop, drop->angle, 8*mapobjectscale); + drop->momz *= 8; } - - P_InstaThrust(drop, drop->angle, 8*mapobjectscale); - - drop->momz *= 8; K_FlipFromObject(drop, monitor); From 18d84c6c2c5aa3a93ba745f078d5be88975fe5ae Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sat, 20 May 2023 14:35:48 -0700 Subject: [PATCH 24/29] Fix instawhip follow hitlag --- src/k_collide.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_collide.cpp b/src/k_collide.cpp index d2b886048..a129d6c44 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -915,7 +915,7 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim) P_DamageMobj(victim, shield, attacker, 1, DMG_NORMAL); K_AddHitLag(attacker, attackerHitlag, false); - shield = attacker; + shield->hitlag = attacker->hitlag; } return false; } From d9dda87586df7b358285f243cc80cb10d1f1ef6f Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sat, 20 May 2023 16:30:35 -0700 Subject: [PATCH 25/29] Hide hitbox on nocollide whip --- src/objects/instawhip.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/objects/instawhip.c b/src/objects/instawhip.c index 10f25fd43..4c711a8b0 100644 --- a/src/objects/instawhip.c +++ b/src/objects/instawhip.c @@ -35,5 +35,8 @@ void Obj_InstaWhipThink (mobj_t *whip) whip->renderflags &= ~RF_DONTDRAW; else whip->renderflags |= RF_DONTDRAW; + + if (whip->extravalue2) // Whip has no hitbox but removing it is a pain in the ass + whip->renderflags |= RF_DONTDRAW; } } \ No newline at end of file From ce7e083e133220ac36179bf17bbb2517591460a1 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 25 May 2023 15:31:33 -0400 Subject: [PATCH 26/29] Bots: Add instashield behaviors Also tidied up some of the ring usage code. --- src/k_botitem.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 83 insertions(+), 3 deletions(-) diff --git a/src/k_botitem.c b/src/k_botitem.c index 8758db8dc..c1f818a97 100644 --- a/src/k_botitem.c +++ b/src/k_botitem.c @@ -1362,6 +1362,18 @@ static void K_BotItemRings(player_t *player, ticcmd_t *cmd) { INT32 saferingsval = 16 - K_GetKartRingPower(player, false); + if (leveltime < starttime) + { + // Don't use rings during POSITION!! + return; + } + + if ((cmd->buttons & BT_ACCELERATE) == 0) + { + // Don't use rings if you're not trying to accelerate. + return; + } + if (P_IsObjectOnGround(player->mo) == false) { // Don't use while mid-air. @@ -1380,6 +1392,70 @@ static void K_BotItemRings(player_t *player, ticcmd_t *cmd) } } +/*-------------------------------------------------- + static void K_BotItemInstashield(player_t *player, ticcmd_t *cmd) + + Item usage for instashield. + + Input Arguments:- + player - Bot to do this for. + cmd - Bot's ticcmd to edit. + + Return:- + None +--------------------------------------------------*/ +static void K_BotItemInstashield(player_t *player, ticcmd_t *cmd) +{ + const fixed_t radius = FixedMul(mobjinfo[MT_INSTAWHIP].radius, player->mo->scale); + size_t i = SIZE_MAX; + + if (K_ItemButtonWasDown(player) == true) + { + // Release the button, dude. + return; + } + + if (player->instaShieldCooldown || leveltime < starttime || player->spindash) + { + // Instashield is on cooldown. + return; + } + + // Find players within the instashield's range. + for (i = 0; i < MAXPLAYERS; i++) + { + player_t *target = NULL; + fixed_t dist = INT32_MAX; + + if (!playeringame[i]) + { + continue; + } + + target = &players[i]; + if (P_MobjWasRemoved(target->mo) == true + || player == target + || target->spectator == true + || target->flashing != 0) + { + continue; + } + + dist = P_AproxDistance(P_AproxDistance( + player->mo->x - target->mo->x, + player->mo->y - target->mo->y), + (player->mo->z - target->mo->z) / 4 + ); + + if (dist <= radius) + { + // Use it!! + cmd->buttons |= BT_ATTACK; + break; + } + } +} + /*-------------------------------------------------- static void K_BotItemRouletteMash(player_t *player, ticcmd_t *cmd) @@ -1453,12 +1529,16 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) { if (player->pflags & PF_USERINGS) { - // Use rings! - - if (leveltime > starttime) + if (player->rings > 0) { + // Use rings! K_BotItemRings(player, cmd); } + else + { + // Use the instashield! + K_BotItemInstashield(player, cmd); + } } else { From 20f57d7efaea46d79fc8a0656526ced642ffc01c Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Thu, 25 May 2023 22:49:14 -0700 Subject: [PATCH 27/29] Don't drop emeralds unless it's a new hit --- src/d_player.h | 2 ++ src/k_battle.c | 3 +++ src/k_kart.c | 5 +++++ src/p_saveg.c | 2 ++ 4 files changed, 12 insertions(+) diff --git a/src/d_player.h b/src/d_player.h index 2e7aeae1b..f59a95356 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -746,6 +746,8 @@ struct player_t UINT8 instaShieldCooldown; UINT8 guardCooldown; + UINT16 incontrol; + uint8_t public_key[PUBKEYLENGTH]; #ifdef HWRENDER diff --git a/src/k_battle.c b/src/k_battle.c index d7997a809..7c6dd7d09 100644 --- a/src/k_battle.c +++ b/src/k_battle.c @@ -265,6 +265,9 @@ void K_DropEmeraldsFromPlayer(player_t *player, UINT32 emeraldType) UINT8 i; SINT8 flip = P_MobjFlip(player->mo); + if (player->incontrol < TICRATE) + return; + for (i = 0; i < 14; i++) { UINT32 emeraldFlag = (1 << i); diff --git a/src/k_kart.c b/src/k_kart.c index 6cd6a0d76..207cea726 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8031,6 +8031,11 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->tiregrease) player->tiregrease--; + if (player->spinouttimer || player->tumbleBounces) + player->incontrol = 0; + else + player->incontrol++; + if (player->tumbleBounces > 0) { K_HandleTumbleSound(player); diff --git a/src/p_saveg.c b/src/p_saveg.c index 013d81830..090951899 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -428,6 +428,7 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT8(save->p, players[i].instaShieldCooldown); WRITEUINT8(save->p, players[i].guardCooldown); + WRITEUINT16(save->p, players[i].incontrol); // respawnvars_t WRITEUINT8(save->p, players[i].respawn.state); @@ -819,6 +820,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].instaShieldCooldown = READUINT8(save->p); players[i].guardCooldown = READUINT8(save->p); + players[i].incontrol = READUINT16(save->p); // respawnvars_t players[i].respawn.state = READUINT8(save->p); From 4c927b09d11bf72d4ad9191f611477c0b2a2be2a Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sun, 28 May 2023 15:12:08 -0700 Subject: [PATCH 28/29] Review fixup --- src/d_player.h | 2 +- src/k_kart.c | 19 +++++++++++++++---- src/objects/block.c | 2 +- src/objects/instawhip.c | 2 +- src/p_saveg.c | 4 ++-- 5 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index f59a95356..fe39ea586 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -746,7 +746,7 @@ struct player_t UINT8 instaShieldCooldown; UINT8 guardCooldown; - UINT16 incontrol; + INT16 incontrol; // -1 to -175 when spinning out or tumbling, 1 to 175 when not. Use to check for combo hits or emergency inputs. uint8_t public_key[PUBKEYLENGTH]; diff --git a/src/k_kart.c b/src/k_kart.c index 207cea726..849f9b255 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7812,7 +7812,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) // where's the < 0 check? see below the following block! { - tic_t spheredigestion = TICRATE*2; // Base rate of 1 every second when playing. + tic_t spheredigestion = TICRATE*2; // Base rate of 1 every 2 seconds when playing. tic_t digestionpower = ((10 - player->kartspeed) + (10 - player->kartweight))-1; // 1 to 17 // currently 0-34 @@ -7926,7 +7926,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->guardCooldown--; if (player->whip && P_MobjWasRemoved(player->whip)) - player->whip = NULL; + player->whip = P_SetTarget(&player->whip, NULL); if (player->startboost > 0 && onground == true) { @@ -8032,9 +8032,20 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->tiregrease--; if (player->spinouttimer || player->tumbleBounces) - player->incontrol = 0; + { + if (player->incontrol > 0) + player->incontrol = 0; + player->incontrol--; + } else + { + if (player->incontrol < 0) + player->incontrol = 0; player->incontrol++; + } + + player->incontrol = min(player->incontrol, 5*TICRATE); + player->incontrol = max(player->incontrol, -5*TICRATE); if (player->tumbleBounces > 0) { @@ -10626,7 +10637,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->guardCooldown = 50; S_StartSound(player->mo, sfx_iwhp); mobj_t *whip = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_INSTAWHIP); - player->whip = whip; + player->whip = P_SetTarget(&player->whip, whip); P_SetScale(whip, player->mo->scale); P_SetTarget(&whip->target, player->mo); K_MatchGenericExtraFlags(whip, player->mo); diff --git a/src/objects/block.c b/src/objects/block.c index 1d715ecbe..b2d70ed49 100644 --- a/src/objects/block.c +++ b/src/objects/block.c @@ -81,4 +81,4 @@ void Obj_GuardBreakThink (mobj_t *fx) fx->renderflags &= ~RF_DONTDRAW; else fx->renderflags |= RF_DONTDRAW; -} \ No newline at end of file +} diff --git a/src/objects/instawhip.c b/src/objects/instawhip.c index 4c711a8b0..f7abb9640 100644 --- a/src/objects/instawhip.c +++ b/src/objects/instawhip.c @@ -39,4 +39,4 @@ void Obj_InstaWhipThink (mobj_t *whip) if (whip->extravalue2) // Whip has no hitbox but removing it is a pain in the ass whip->renderflags |= RF_DONTDRAW; } -} \ No newline at end of file +} diff --git a/src/p_saveg.c b/src/p_saveg.c index 090951899..6a71bf4f1 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -428,7 +428,7 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT8(save->p, players[i].instaShieldCooldown); WRITEUINT8(save->p, players[i].guardCooldown); - WRITEUINT16(save->p, players[i].incontrol); + WRITEINT16(save->p, players[i].incontrol); // respawnvars_t WRITEUINT8(save->p, players[i].respawn.state); @@ -820,7 +820,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].instaShieldCooldown = READUINT8(save->p); players[i].guardCooldown = READUINT8(save->p); - players[i].incontrol = READUINT16(save->p); + players[i].incontrol = READINT16(save->p); // respawnvars_t players[i].respawn.state = READUINT8(save->p); From 47a63e1ca2217cf4319dc22c9b3962c9627eb931 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sun, 28 May 2023 16:07:32 -0700 Subject: [PATCH 29/29] If I ever see another macro I'm going to burn down John Carmack's house --- src/k_kart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 849f9b255..dded2750d 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7926,7 +7926,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->guardCooldown--; if (player->whip && P_MobjWasRemoved(player->whip)) - player->whip = P_SetTarget(&player->whip, NULL); + P_SetTarget(&player->whip, NULL); if (player->startboost > 0 && onground == true) { @@ -10637,7 +10637,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->guardCooldown = 50; S_StartSound(player->mo, sfx_iwhp); mobj_t *whip = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_INSTAWHIP); - player->whip = P_SetTarget(&player->whip, whip); + P_SetTarget(&player->whip, whip); P_SetScale(whip, player->mo->scale); P_SetTarget(&whip->target, player->mo); K_MatchGenericExtraFlags(whip, player->mo);