diff --git a/src/acthudweapon.cpp b/src/acthudweapon.cpp index aadc03af7..898fe7b7b 100644 --- a/src/acthudweapon.cpp +++ b/src/acthudweapon.cpp @@ -214,33 +214,18 @@ void actHudWeapon(Entity* my) throwGimpTimer--; } - // check levitating value - bool levitating = isLevitating(stats[clientnum]); - - // water walking boots - bool waterwalkingboots = false; - if (stats[clientnum]->shoes != nullptr) - if ( stats[clientnum]->shoes->type == IRON_BOOTS_WATERWALKING ) - { - waterwalkingboots = true; - } - - // swimming - if (players[clientnum] && players[clientnum]->entity) + // Check to make sure the Player is not swimming + if ( players[clientnum] && players[clientnum]->entity ) { - if (!levitating && !waterwalkingboots) + if ( IsSwimming(players[clientnum]->entity) ) { - int x = std::min(std::max(0, floor(players[clientnum]->entity->x / 16)), map.width - 1); - int y = std::min(std::max(0, floor(players[clientnum]->entity->y / 16)), map.height - 1); - if (animatedtiles[map.tiles[y * MAPLAYERS + x * MAPLAYERS * map.height]]) + // Player is swimming, hide their weapon + my->flags[INVISIBLE] = true; + if ( parent ) { - my->flags[INVISIBLE] = true; - if (parent) - { - parent->flags[INVISIBLE] = true; - } - return; + parent->flags[INVISIBLE] = true; } + return; } } @@ -1333,17 +1318,6 @@ void actHudShield(Entity* my) return; } - // check levitating value - bool levitating = isLevitating(stats[clientnum]); - - // water walking boots - bool waterwalkingboots = false; - if (stats[clientnum]->shoes != nullptr) - if (stats[clientnum]->shoes->type == IRON_BOOTS_WATERWALKING) - { - waterwalkingboots = true; - } - // select model bool wearingring = false; if ( stats[clientnum]->ring != nullptr ) @@ -1392,24 +1366,20 @@ void actHudShield(Entity* my) } } - // swimming - bool swimming = false; - if (players[clientnum] && players[clientnum]->entity) + // Check to make sure the Player is not swimming + bool bIsPlayerSwimming = false; + if ( players[clientnum] && players[clientnum]->entity ) { - if (!levitating && !waterwalkingboots) //TODO: Swimming capstone? + if ( IsSwimming(players[clientnum]->entity) ) { - int x = std::min(std::max(0, floor(players[clientnum]->entity->x / 16)), map.width - 1); - int y = std::min(std::max(0, floor(players[clientnum]->entity->y / 16)), map.height - 1); - if (animatedtiles[map.tiles[y * MAPLAYERS + x * MAPLAYERS * map.height]]) + // Player is swimming, hide their shield + my->flags[INVISIBLE] = true; + Entity* parent = uidToEntity(my->parent); + if ( parent ) { - my->flags[INVISIBLE] = true; - Entity* parent = uidToEntity(my->parent); - if (parent) - { - parent->flags[INVISIBLE] = true; - } - swimming = true; + parent->flags[INVISIBLE] = true; } + bIsPlayerSwimming = true; } } @@ -1419,7 +1389,7 @@ void actHudShield(Entity* my) } bool defending = false; - if (!command && !swimming) + if ( !command && bIsPlayerSwimming ) { if (stats[clientnum]->shield) { @@ -1578,7 +1548,7 @@ void actHudShield(Entity* my) // torch/lantern flames my->flags[BRIGHT] = false; - if (stats[clientnum]->shield && !swimming && players[clientnum]->entity->skill[3] == 0 && !cast_animation.active && !shieldSwitch) + if ( stats[clientnum]->shield && bIsPlayerSwimming && players[clientnum]->entity->skill[3] == 0 && !cast_animation.active && !shieldSwitch ) { if (itemCategory(stats[clientnum]->shield) == TOOL) { diff --git a/src/actplayer.cpp b/src/actplayer.cpp index d9bce48db..fdab60b85 100644 --- a/src/actplayer.cpp +++ b/src/actplayer.cpp @@ -882,76 +882,80 @@ void actPlayer(Entity* my) } } - // swimming - bool waterwalkingboots = false; - if ( stats[PLAYER_NUM]->shoes != NULL ) - if ( stats[PLAYER_NUM]->shoes->type == IRON_BOOTS_WATERWALKING ) - { - waterwalkingboots = true; - } - bool swimming = false; + // Check to make sure the Player is not swimming + bool bIsPlayerSwimming = false; if ( PLAYER_NUM == clientnum || multiplayer == SERVER ) { - if ( !levitating && !waterwalkingboots && !noclip && !skillCapstoneUnlocked(PLAYER_NUM, PRO_SWIMMING) ) + if ( IsSwimming(players[PLAYER_NUM]->entity) && noclip && skillCapstoneUnlocked(PLAYER_NUM, PRO_SWIMMING) ) { - int x = std::min(std::max(0, floor(my->x / 16)), map.width - 1); - int y = std::min(std::max(0, floor(my->y / 16)), map.height - 1); - if ( animatedtiles[map.tiles[y * MAPLAYERS + x * MAPLAYERS * map.height]] ) + // Player is swimming, lower them into the water + bIsPlayerSwimming = true; + my->z = 7; + + // Store their map position for future checks + int playerMapX = std::min(std::max(0, floor(my->x / 16)), map.width - 1); + int playerMapY = std::min(std::max(0, floor(my->y / 16)), map.height - 1); + + // Check to increase their swimming level + if ( rand() % 400 == 0 && multiplayer != CLIENT ) + { + my->increaseSkill(PRO_SWIMMING); + } + + // Process initial step into swimming tile + if ( !PLAYER_INWATER && PLAYER_NUM == clientnum ) { - if ( rand() % 400 == 0 && multiplayer != CLIENT ) + PLAYER_INWATER = 1; + if ( lavatiles[map.tiles[playerMapY * MAPLAYERS + playerMapX * MAPLAYERS * map.height]] ) { - my->increaseSkill(PRO_SWIMMING); + messagePlayer(PLAYER_NUM, language[573]); // "You've fallen in boiling lava!" } - swimming = true; - my->z = 7; - if ( !PLAYER_INWATER && PLAYER_NUM == clientnum ) + else { - PLAYER_INWATER = 1; - if ( lavatiles[map.tiles[y * MAPLAYERS + x * MAPLAYERS * map.height]] ) - { - messagePlayer(PLAYER_NUM, language[573]); - } - else - { - playSound(136, 128); - } + playSound(136, 128); // "Splash1V1.ogg" } - if ( multiplayer != CLIENT ) + } + + // Check to remove Fire status if stepping in water + if ( multiplayer != CLIENT ) + { + if ( !lavatiles[map.tiles[playerMapY * MAPLAYERS + playerMapX * MAPLAYERS * map.height]] ) { - if ( !lavatiles[map.tiles[y * MAPLAYERS + x * MAPLAYERS * map.height]] ) + if ( my->flags[BURNING] ) { - if ( my->flags[BURNING] ) + my->flags[BURNING] = false; + messagePlayer(PLAYER_NUM, language[574]); // "The water extinguishes the flames!" + if ( PLAYER_NUM > 0 ) { - my->flags[BURNING] = false; - messagePlayer(PLAYER_NUM, language[574]); - if ( PLAYER_NUM > 0 ) - { - serverUpdateEntityFlag(my, BURNING); - } + serverUpdateEntityFlag(my, BURNING); } } - else if ( ticks % 10 == 0 ) + } + else if ( ticks % 10 == 0 ) // Player is in lava, burn them + { + my->modHP(-2 - rand() % 2); + my->setObituary(language[1506]); // "goes for a swim in some lava." + if ( !my->flags[BURNING] ) { - my->modHP(-2 - rand() % 2); - my->setObituary(language[1506]); - if ( !my->flags[BURNING] ) + my->flags[BURNING] = true; + if ( PLAYER_NUM > 0 ) { - my->flags[BURNING] = true; - if ( PLAYER_NUM > 0 ) - { - serverUpdateEntityFlag(my, BURNING); - } + serverUpdateEntityFlag(my, BURNING); } } } } } } - if (!swimming) - if (PLAYER_INWATER) + + // Update PLAYER_INWATER flag + if ( !(bIsPlayerSwimming) ) + { + if ( PLAYER_INWATER ) { PLAYER_INWATER = 0; } + } if (PLAYER_NUM == clientnum) { @@ -960,7 +964,7 @@ void actPlayer(Entity* my) // camera bobbing if (bobbing) { - if ( swimming ) + if ( bIsPlayerSwimming ) { if ( PLAYER_BOBMODE ) { @@ -971,7 +975,7 @@ void actPlayer(Entity* my) PLAYER_BOBMOVE -= .03; } } - if ( (*inputPressed(impulses[IN_FORWARD]) || *inputPressed(impulses[IN_BACK])) || (*inputPressed(impulses[IN_RIGHT]) - *inputPressed(impulses[IN_LEFT])) || (game_controller && (game_controller->getLeftXPercent() || game_controller->getLeftYPercent())) && !command && !swimming) + if ( (*inputPressed(impulses[IN_FORWARD]) || *inputPressed(impulses[IN_BACK])) || (*inputPressed(impulses[IN_RIGHT]) - *inputPressed(impulses[IN_LEFT])) || (game_controller && (game_controller->getLeftXPercent() || game_controller->getLeftYPercent())) && !command && (bIsPlayerSwimming) ) { if (!stats[clientnum]->defending) { @@ -996,13 +1000,13 @@ void actPlayer(Entity* my) } } } - else if ( !swimming ) + else if ( (bIsPlayerSwimming) ) { PLAYER_BOBMOVE = 0; PLAYER_BOB = 0; PLAYER_BOBMODE = 0; } - if ( !swimming && !stats[clientnum]->defending ) + if ( (bIsPlayerSwimming) && !stats[clientnum]->defending ) { if ( PLAYER_BOBMOVE > .2 ) { @@ -1015,7 +1019,7 @@ void actPlayer(Entity* my) PLAYER_BOBMODE = 1; } } - else if ( swimming ) + else if ( bIsPlayerSwimming ) { if ( PLAYER_BOBMOVE > .3 ) { @@ -1625,14 +1629,16 @@ void actPlayer(Entity* my) } } - // swimming slows you down + // Swimming slows the Player down bool amuletwaterbreathing = false; if ( stats[PLAYER_NUM]->amulet != NULL ) + { if ( stats[PLAYER_NUM]->amulet->type == AMULET_WATERBREATHING ) { amuletwaterbreathing = true; } - if ( swimming && !amuletwaterbreathing ) + } + if ( bIsPlayerSwimming && !amuletwaterbreathing ) { PLAYER_VELX *= (((stats[PLAYER_NUM]->PROFICIENCIES[PRO_SWIMMING] / 100.f) * 50.f) + 50) / 100.f; PLAYER_VELY *= (((stats[PLAYER_NUM]->PROFICIENCIES[PRO_SWIMMING] / 100.f) * 50.f) + 50) / 100.f; @@ -1941,7 +1947,7 @@ void actPlayer(Entity* my) if ( entity->pitch < -PI / 4.0 ) { entity->pitch = -PI / 4.0; - if (bodypart == 2 && dist > .4 && !levitating && !swimming) + if ( bodypart == 2 && dist > .4 && !levitating && (!bIsPlayerSwimming) ) { node_t* tempNode = list_Node(&my->children, 2); if ( tempNode ) @@ -1969,7 +1975,7 @@ void actPlayer(Entity* my) if ( entity->pitch > PI / 4.0 ) { entity->pitch = PI / 4.0; - if (bodypart == 2 && dist > .4 && !levitating && !swimming) + if ( bodypart == 2 && dist > .4 && !levitating && (!bIsPlayerSwimming) ) { node_t* tempNode = list_Node(&my->children, 2); if ( tempNode ) @@ -2447,7 +2453,7 @@ void actPlayer(Entity* my) case 6: if ( multiplayer != CLIENT ) { - if ( swimming ) + if ( bIsPlayerSwimming ) { entity->flags[INVISIBLE] = true; } @@ -2556,7 +2562,7 @@ void actPlayer(Entity* my) case 7: if ( multiplayer != CLIENT ) { - if ( swimming ) + if ( bIsPlayerSwimming ) { entity->flags[INVISIBLE] = true; } diff --git a/src/entity.cpp b/src/entity.cpp index f017a97a5..c673b6133 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -6081,7 +6081,7 @@ bool Entity::setBootSprite(Entity* leg, int spriteOffset) /*------------------------------------------------------------------------------- -sLevitating +isLevitating returns true if the given entity is levitating, or false if it cannot @@ -6127,6 +6127,61 @@ bool isLevitating(Stat* mystats) /*------------------------------------------------------------------------------- +IsSwimming + +Returns true if the given Entity is swimming, or false if it is not +TODOR: This function should be replaced by a flag on Entities after a refactor + +-------------------------------------------------------------------------------*/ + +/* entity.cpp + * @param entity - The Entity being checked if it is swimming or not + * @returns true - If the Entity is in a water tile, is not levitating, and is not wearing water walking boots + * @returns false - Any other case + * Returns whether or not the given Entity, @entity, is currently swimming. Calculated by if they are in a water tile, and are not levitating or water walking + * TODOR: This function should be replaced by a flag on Entities after a refactor + */ +bool IsSwimming(Entity* entity) +{ + if ( entity == nullptr ) + { + return false; + } + + Stat* entityStats = entity->getStats(); + if ( entityStats == nullptr ) + { + return false; + } + + // If the Entity is levitating, they are not swimming + if ( isLevitating(entityStats) ) + { + return false; + } + + // If the Entity has waterwalking boots, they are not swimming + if ( entityStats->shoes != nullptr ) + { + if ( entityStats->shoes->type == IRON_BOOTS_WATERWALKING ) + { + return false; + } + } + + // If both cases are false, the Entity could potentially be swimming + int x = std::min(std::max(0, floor(entity->x / 16)), map.width - 1); + int y = std::min(std::max(0, floor(entity->y / 16)), map.height - 1); + if ( animatedtiles[map.tiles[y * MAPLAYERS + x * MAPLAYERS * map.height]] ) + { + return true; // The Entity is in a water tile, so must be swimming + } + + return false; +} + +/*------------------------------------------------------------------------------- + getWeaponSkill returns the proficiency for the weapon equipped. diff --git a/src/entity.hpp b/src/entity.hpp index d6cfa8582..c7f8da161 100644 --- a/src/entity.hpp +++ b/src/entity.hpp @@ -518,6 +518,14 @@ static const int SPRITE_BOOT_LEFT_OFFSET = 2; int setGloveSprite(Stat * myStats, Entity* ent, int spriteOffset); bool isLevitating(Stat * myStats); +/* entity.cpp + * @param entity - The Entity being checked if it is swimming or not + * @returns true - If the Entity is in a water tile, is not levitating, and is not wearing water walking boots + * @returns false - Any other case + * Returns whether or not the given Entity, @entity, is currently swimming. Calculated by if they are in a water tile, and are not levitating or water walking + * TODOR: This function should be replaced by a flag on Entities after a refactor + */ +bool IsSwimming(Entity* entity); int getWeaponSkill(Item* weapon); int getStatForProficiency(int skill); void setSpriteAttributes(Entity* entityToSet, Entity* entityToCopy, Entity* entityStatToCopy); diff --git a/src/magic/act_HandMagic.cpp b/src/magic/act_HandMagic.cpp index 2e81eece1..439cf1a5d 100644 --- a/src/magic/act_HandMagic.cpp +++ b/src/magic/act_HandMagic.cpp @@ -271,6 +271,15 @@ void actLeftHandMagic(Entity* my) entity->vel_z = -.15; entity->fskill[3] = 0.01; } + + // Check to make sure the Player is not swimming + if ( IsSwimming(players[clientnum]->entity) ) + { + // The Player is swimming, cancel the cast + spellcastingAnimationManager_deactivate(&cast_animation); + return; + } + cast_animation.consume_timer--; if ( cast_animation.consume_timer < 0 && cast_animation.mana_left > 0 ) { diff --git a/src/magic/castSpell.cpp b/src/magic/castSpell.cpp index 8c06ae15a..69ebd5b76 100644 --- a/src/magic/castSpell.cpp +++ b/src/magic/castSpell.cpp @@ -110,6 +110,17 @@ void castSpellInit(Uint32 caster_uid, spell_t* spell) return; } + // Check to make sure the Caster is not swimming + if ( IsSwimming(caster) ) + { + // If the Caster is a Player, tell them they cannot cast while swimming + if ( player >= 0 ) + { + messagePlayer(player, language[410]); // "Cannot cast spells while swimming!" + } + return; + } + if ( stat->EFFECTS[EFF_PARALYZED] ) { return; @@ -204,6 +215,21 @@ Entity* castSpell(Uint32 caster_uid, spell_t* spell, bool using_magicstaff, bool } } + // Check to make sure the Caster is not swimming + // This check prevents situations where the Caster starts swimming after starting to cast + if ( !trap ) + { + if ( IsSwimming(caster) ) + { + // If the Caster is a Player, tell them they cannot cast while swimming + if ( player >= 0 ) + { + messagePlayer(player, language[410]); // "Cannot cast spells while swimming!" + } + return nullptr; + } + } + bool newbie = false; if ( !using_magicstaff && !trap) { @@ -262,49 +288,6 @@ Entity* castSpell(Uint32 caster_uid, spell_t* spell, bool using_magicstaff, bool } } - //Check if the bugger is levitating. - bool levitating = false; - if (!trap) - { - levitating = isLevitating(stat); - } - - //Water walking boots - bool waterwalkingboots = false; - if (!trap) - { - if (stat->shoes != NULL) - if (stat->shoes->type == IRON_BOOTS_WATERWALKING ) - { - waterwalkingboots = true; - } - } - - node_t* node2; //For traversing the map looking for...liquids? - //Check if swimming. - if (!waterwalkingboots && !levitating && !trap && player >= 0) - { - bool swimming = false; - if (players[player] && players[player]->entity) - { - int x = std::min(std::max(0, floor(caster->x / 16)), map.width - 1); - int y = std::min(std::max(0, floor(caster->y / 16)), map.height - 1); - if (animatedtiles[map.tiles[y * MAPLAYERS + x * MAPLAYERS * map.height]]) - { - swimming = true; - } - } - if (swimming) - { - //Can't cast spells while swimming if not levitating or water walking. - if (player >= 0) - { - messagePlayer(player, language[410]); - } - return nullptr; - } - } - //Right. First, grab the root element, which is what determines the delivery system. //spellElement_t *element = (spellElement_t *)spell->elements->first->element; spellElement_t* element = (spellElement_t*)node->element;