mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2025-10-30 08:01:01 +00:00
Update revamped PVP (#660)
* Fix water punches to include pitch in their range * Allow rollouts to deal damage again
This commit is contained in:
parent
8570cfd4fc
commit
34e20e763d
1 changed files with 44 additions and 27 deletions
|
|
@ -153,9 +153,13 @@ u32 determine_interaction(struct MarioState *m, struct Object *o) {
|
||||||
|
|
||||||
// hack: make water punch actually do something
|
// hack: make water punch actually do something
|
||||||
if (interaction == 0 && m->action == ACT_WATER_PUNCH && o->oInteractType & INTERACT_PLAYER) {
|
if (interaction == 0 && m->action == ACT_WATER_PUNCH && o->oInteractType & INTERACT_PLAYER) {
|
||||||
s16 dYawToObject = mario_obj_angle_to_object(m, o) - m->faceAngle[1];
|
f32 cossFaceAngle0 = coss(m->faceAngle[0]);
|
||||||
// 120 degrees total, or 60 each way
|
Vec3f facing = { coss(m->faceAngle[1])*cossFaceAngle0, sins(m->faceAngle[0]), sins(m->faceAngle[1])*cossFaceAngle0 };
|
||||||
if (-0x2AAA <= dYawToObject && dYawToObject <= 0x2AAA) {
|
Vec3f dif = { o->oPosX - m->pos[0], (o->oPosY + o->hitboxHeight * 0.5) - m->pos[1], o->oPosZ - m->pos[2] };
|
||||||
|
vec3f_normalize(dif);
|
||||||
|
f32 angle = vec3f_dot(facing, dif);
|
||||||
|
// Unknown angle (60 degrees in each direction?)
|
||||||
|
if (angle >= 0.5f) {
|
||||||
interaction = INT_PUNCH;
|
interaction = INT_PUNCH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -680,9 +684,9 @@ u32 determine_knockback_action(struct MarioState *m, UNUSED s32 arg) {
|
||||||
if (m2->marioObj == NULL) { continue; }
|
if (m2->marioObj == NULL) { continue; }
|
||||||
if (m2->marioObj != m->interactObj) { continue; }
|
if (m2->marioObj != m->interactObj) { continue; }
|
||||||
// Redundent check in case the kicking flag somehow gets missed
|
// Redundent check in case the kicking flag somehow gets missed
|
||||||
if (m2->action == ACT_JUMP_KICK || m2->flags & MARIO_KICKING) { scaler = IF_REVAMPED_PVP(1.85f, 2.0f); }
|
if (m2->action == ACT_JUMP_KICK || m2->flags & MARIO_KICKING) { scaler = IF_REVAMPED_PVP(1.9f, 2.0f); }
|
||||||
else if (m2->action == ACT_DIVE) { scaler = 1.0f + IF_REVAMPED_PVP(m2->forwardVel * 0.005f, 0.0f); }
|
else if (m2->action == ACT_DIVE) { scaler = 1.0f + IF_REVAMPED_PVP(m2->forwardVel * 0.005f, 0.0f); }
|
||||||
else if ((m2->flags & MARIO_PUNCHING)) { scaler = IF_REVAMPED_PVP(0.18f, 1.0f); hasBeenPunched = gServerSettings.pvpType == PLAYER_PVP_REVAMPED; }
|
else if ((m2->flags & MARIO_PUNCHING)) { scaler = IF_REVAMPED_PVP(-0.1f, 1.0f); hasBeenPunched = gServerSettings.pvpType == PLAYER_PVP_REVAMPED; }
|
||||||
if (m2->flags & MARIO_METAL_CAP) { scaler *= 1.25f; }
|
if (m2->flags & MARIO_METAL_CAP) { scaler *= 1.25f; }
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -696,9 +700,9 @@ u32 determine_knockback_action(struct MarioState *m, UNUSED s32 arg) {
|
||||||
m->forwardVel = mag;
|
m->forwardVel = mag;
|
||||||
if (sign > 0 && terrainIndex == 1) { mag *= -1.0f; }
|
if (sign > 0 && terrainIndex == 1) { mag *= -1.0f; }
|
||||||
|
|
||||||
m->vel[0] = -mag * sins(m->interactObj->oFaceAngleYaw);
|
m->vel[0] = (-mag * sins(m->interactObj->oFaceAngleYaw)) * IF_REVAMPED_PVP(1.1f, 1.0f);
|
||||||
m->vel[1] = (mag < 0) ? -mag : mag;
|
m->vel[1] = ((mag < 0) ? -mag : mag) * IF_REVAMPED_PVP(0.9f, 1.0f);
|
||||||
m->vel[2] = -mag * coss(m->interactObj->oFaceAngleYaw);
|
m->vel[2] = (-mag * coss(m->interactObj->oFaceAngleYaw)) * IF_REVAMPED_PVP(1.1f, 1.0f);
|
||||||
m->slideVelX = m->vel[0];
|
m->slideVelX = m->vel[0];
|
||||||
m->slideVelZ = m->vel[2];
|
m->slideVelZ = m->vel[2];
|
||||||
m->knockbackTimer = hasBeenPunched ? PVP_ATTACK_KNOCKBACK_TIMER_OVERRIDE : PVP_ATTACK_KNOCKBACK_TIMER_DEFAULT;
|
m->knockbackTimer = hasBeenPunched ? PVP_ATTACK_KNOCKBACK_TIMER_OVERRIDE : PVP_ATTACK_KNOCKBACK_TIMER_DEFAULT;
|
||||||
|
|
@ -1327,15 +1331,18 @@ static u8 resolve_player_collision(struct MarioState* m, struct MarioState* m2)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 determine_player_damage_value(u32 interaction) {
|
u8 determine_player_damage_value(struct MarioState* attacker, u32 interaction) {
|
||||||
if (gServerSettings.pvpType == PLAYER_PVP_REVAMPED) {
|
if (gServerSettings.pvpType == PLAYER_PVP_REVAMPED) {
|
||||||
if (interaction & INT_GROUND_POUND) { return 3; }
|
if (attacker->action == ACT_GROUND_POUND_LAND) { return 2; }
|
||||||
if (interaction & (INT_KICK | INT_SLIDE_KICK | INT_TRIP | INT_TWIRL)) { return 2; }
|
else if (interaction & INT_GROUND_POUND) { return 3; }
|
||||||
|
else if (interaction & (INT_KICK | INT_SLIDE_KICK | INT_TRIP | INT_TWIRL)) { return 2; }
|
||||||
|
else if (interaction & INT_PUNCH && attacker->actionArg < 3) { return 2; }
|
||||||
|
else if (attacker->action == ACT_FLYING) { return (u8)(attacker->forwardVel / 75.0f) + 1; }
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
if (interaction & INT_GROUND_POUND_OR_TWIRL) { return 3; }
|
if (interaction & INT_GROUND_POUND_OR_TWIRL) { return 3; }
|
||||||
if (interaction & INT_KICK) { return 2; }
|
else if (interaction & INT_KICK) { return 2; }
|
||||||
if (interaction & INT_ATTACK_SLIDE) { return 1; }
|
else if (interaction & INT_ATTACK_SLIDE) { return 1; }
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1369,23 +1376,21 @@ u8 passes_pvp_interaction_checks(struct MarioState* attacker, struct MarioState*
|
||||||
|| attacker->action == ACT_BACKFLIP || attacker->action == ACT_TRIPLE_JUMP
|
|| attacker->action == ACT_BACKFLIP || attacker->action == ACT_TRIPLE_JUMP
|
||||||
|| attacker->action == ACT_WALL_KICK_AIR || attacker->action == ACT_WATER_JUMP
|
|| attacker->action == ACT_WALL_KICK_AIR || attacker->action == ACT_WATER_JUMP
|
||||||
|| attacker->action == ACT_STEEP_JUMP || attacker->action == ACT_HOLD_JUMP
|
|| attacker->action == ACT_STEEP_JUMP || attacker->action == ACT_HOLD_JUMP
|
||||||
|| attacker->action == ACT_FREEFALL || attacker->action == ACT_LEDGE_GRAB
|
|| attacker->action == ACT_FREEFALL || attacker->action == ACT_LEDGE_GRAB);
|
||||||
|| attacker->action == ACT_FORWARD_ROLLOUT || attacker->action == ACT_BACKWARD_ROLLOUT);
|
|
||||||
u8 isVictimIntangible = (victim->action & ACT_FLAG_INTANGIBLE);
|
u8 isVictimIntangible = (victim->action & ACT_FLAG_INTANGIBLE);
|
||||||
u8 isVictimGroundPounding = (victim->action == ACT_GROUND_POUND) && (victim->actionState != 0);
|
u8 isVictimGroundPounding = (victim->action == ACT_GROUND_POUND) && (victim->actionState != 0);
|
||||||
u8 isVictimInRolloutFlip = gServerSettings.pvpType == PLAYER_PVP_REVAMPED &&
|
|
||||||
((victim->action == ACT_FORWARD_ROLLOUT || victim->action == ACT_BACKWARD_ROLLOUT) && (victim->actionState == 1));
|
|
||||||
if (victim->knockbackTimer != 0) {
|
if (victim->knockbackTimer != 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gServerSettings.pvpType == PLAYER_PVP_REVAMPED &&
|
if (gServerSettings.pvpType == PLAYER_PVP_REVAMPED &&
|
||||||
(attacker->action == ACT_PUNCHING || attacker->action == ACT_MOVE_PUNCHING) &&
|
(attacker->action == ACT_PUNCHING || attacker->action == ACT_MOVE_PUNCHING) &&
|
||||||
(victim->action == ACT_SOFT_BACKWARD_GROUND_KB || victim->action == ACT_SOFT_FORWARD_GROUND_KB)) {
|
(victim->action == ACT_BACKWARD_GROUND_KB || victim->action == ACT_FORWARD_GROUND_KB ||
|
||||||
|
victim->action == ACT_SOFT_BACKWARD_GROUND_KB || victim->action == ACT_SOFT_FORWARD_GROUND_KB)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (!isInvulnerable && !isIgnoredAttack && !isAttackerInvulnerable && !isVictimIntangible && !isVictimGroundPounding && !isVictimInRolloutFlip);
|
return (!isInvulnerable && !isIgnoredAttack && !isAttackerInvulnerable && !isVictimIntangible && !isVictimGroundPounding);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 interact_player(struct MarioState* m, UNUSED u32 interactType, struct Object* o) {
|
u32 interact_player(struct MarioState* m, UNUSED u32 interactType, struct Object* o) {
|
||||||
|
|
@ -1455,6 +1460,9 @@ u32 interact_player_pvp(struct MarioState* attacker, struct MarioState* victim)
|
||||||
|
|
||||||
// make sure we overlap
|
// make sure we overlap
|
||||||
f32 overlapScale = (attacker->playerIndex == 0) ? 0.6f : 1.0f;
|
f32 overlapScale = (attacker->playerIndex == 0) ? 0.6f : 1.0f;
|
||||||
|
if (gServerSettings.pvpType == PLAYER_PVP_REVAMPED && attacker->action == ACT_GROUND_POUND_LAND) {
|
||||||
|
overlapScale += 0.3f;
|
||||||
|
}
|
||||||
if (!detect_player_hitbox_overlap(attacker, cVictim, overlapScale)) {
|
if (!detect_player_hitbox_overlap(attacker, cVictim, overlapScale)) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
@ -1463,6 +1471,8 @@ u32 interact_player_pvp(struct MarioState* attacker, struct MarioState* victim)
|
||||||
u32 interaction = determine_interaction(attacker, cVictim->marioObj);
|
u32 interaction = determine_interaction(attacker, cVictim->marioObj);
|
||||||
// Specfically override jump kicks to prevent low damage and low knockback kicks
|
// Specfically override jump kicks to prevent low damage and low knockback kicks
|
||||||
if (interaction & INT_HIT_FROM_BELOW && attacker->action == ACT_JUMP_KICK) { interaction = INT_KICK; }
|
if (interaction & INT_HIT_FROM_BELOW && attacker->action == ACT_JUMP_KICK) { interaction = INT_KICK; }
|
||||||
|
// Allow rollouts to attack
|
||||||
|
else if ((attacker->action == ACT_FORWARD_ROLLOUT || attacker->action == ACT_BACKWARD_ROLLOUT) && attacker->actionState == 1) { interaction = INT_HIT_FROM_BELOW; }
|
||||||
if (!(interaction & INT_ANY_ATTACK) || (interaction & INT_HIT_FROM_ABOVE) || !passes_pvp_interaction_checks(attacker, cVictim)) {
|
if (!(interaction & INT_ANY_ATTACK) || (interaction & INT_HIT_FROM_ABOVE) || !passes_pvp_interaction_checks(attacker, cVictim)) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
@ -1476,11 +1486,11 @@ u32 interact_player_pvp(struct MarioState* attacker, struct MarioState* victim)
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine if slide attack should be ignored
|
// determine if slide attack should be ignored
|
||||||
// Ground pounds will always be able to hit
|
|
||||||
if ((interaction & INT_ATTACK_SLIDE) || player_is_sliding(cVictim)) {
|
if ((interaction & INT_ATTACK_SLIDE) || player_is_sliding(cVictim)) {
|
||||||
// determine the difference in velocities
|
// determine the difference in velocities
|
||||||
//Vec3f velDiff;
|
//Vec3f velDiff;
|
||||||
//vec3f_dif(velDiff, attacker->vel, cVictim->vel);
|
//vec3f_dif(velDiff, attacker->vel, cVictim->vel);
|
||||||
|
// Allow groundpounds to always hit sliding/fast attacks
|
||||||
if (gServerSettings.pvpType == PLAYER_PVP_REVAMPED && attacker->action == ACT_GROUND_POUND) {
|
if (gServerSettings.pvpType == PLAYER_PVP_REVAMPED && attacker->action == ACT_GROUND_POUND) {
|
||||||
// do nothing
|
// do nothing
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1492,15 +1502,22 @@ u32 interact_player_pvp(struct MarioState* attacker, struct MarioState* victim)
|
||||||
if (vec3f_length(attacker->vel) < 40) { return FALSE; }
|
if (vec3f_length(attacker->vel) < 40) { return FALSE; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the victim is going faster, do not attack
|
u8 forceAllowAttack = FALSE;
|
||||||
// However if the victim is diving and the attacker is slidekicking, do not check speed
|
if (gServerSettings.pvpType == PLAYER_PVP_REVAMPED) {
|
||||||
if (vec3f_length(cVictim->vel) > vec3f_length(attacker->vel)) {
|
// Give slidekicks trade immunity by making them (almost) invincible
|
||||||
if (gServerSettings.pvpType == PLAYER_PVP_REVAMPED && (attacker->action == ACT_SLIDE_KICK && cVictim->action == ACT_DIVE)) {
|
// Also give rollouts immunity to dives
|
||||||
// do nothing, meaning don't exit
|
if ((cVictim->action == ACT_SLIDE_KICK && attacker->action != ACT_SLIDE_KICK) ||
|
||||||
} else {
|
((cVictim->action == ACT_FORWARD_ROLLOUT || cVictim->action == ACT_BACKWARD_ROLLOUT) && attacker->action == ACT_DIVE)) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
} else if ((attacker->action == ACT_SLIDE_KICK) ||
|
||||||
|
((attacker->action == ACT_FORWARD_ROLLOUT || attacker->action == ACT_BACKWARD_ROLLOUT) && cVictim->action == ACT_DIVE)) {
|
||||||
|
forceAllowAttack = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// if the victim is going faster, do not attack
|
||||||
|
if (vec3f_length(cVictim->vel) > vec3f_length(attacker->vel) && !forceAllowAttack) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1523,7 +1540,7 @@ u32 interact_player_pvp(struct MarioState* attacker, struct MarioState* victim)
|
||||||
set_mario_action(victim, ACT_FREEFALL, 0);
|
set_mario_action(victim, ACT_FREEFALL, 0);
|
||||||
}
|
}
|
||||||
if (!(victim->flags & MARIO_METAL_CAP)) {
|
if (!(victim->flags & MARIO_METAL_CAP)) {
|
||||||
attacker->marioObj->oDamageOrCoinValue = determine_player_damage_value(interaction);
|
attacker->marioObj->oDamageOrCoinValue = determine_player_damage_value(attacker, interaction);
|
||||||
if (attacker->flags & MARIO_METAL_CAP) { attacker->marioObj->oDamageOrCoinValue *= 2; }
|
if (attacker->flags & MARIO_METAL_CAP) { attacker->marioObj->oDamageOrCoinValue *= 2; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue