Goblin Bow users stop aiming 1/3rd of a second before firing, to allow the player to dodge and not cause them to suddenly turn. Added configurable parameter for Goblin Bow lock-in time. Release Build 10188.

removeExposedPackKey
sigonasr2 4 months ago
parent 64f726b50d
commit e0178fb08b
  1. 6
      Adventures in Lestoria Tests/PlayerTests.cpp
  2. 3
      Adventures in Lestoria/Arrow.cpp
  3. 2
      Adventures in Lestoria/BulletTypes.h
  4. 21
      Adventures in Lestoria/Goblin_Bow.cpp
  5. 2
      Adventures in Lestoria/MonsterAttribute.h
  6. 2
      Adventures in Lestoria/Version.h
  7. 3
      Adventures in Lestoria/assets/config/MonsterStrategies.txt
  8. BIN
      x64/Release/Adventures in Lestoria.exe

@ -319,12 +319,6 @@ namespace PlayerTests
player->AddBuff(BuffType::STAT_UP,5.f,1000.0_Pct,{"Health %"}); player->AddBuff(BuffType::STAT_UP,5.f,1000.0_Pct,{"Health %"});
Assert::AreEqual(1000+player->GetBaseStat("Health"),float(player->GetMaxHealth()),L"Max Health stat should be increased from 100 to 1100."); Assert::AreEqual(1000+player->GetBaseStat("Health"),float(player->GetMaxHealth()),L"Max Health stat should be increased from 100 to 1100.");
} }
TEST_METHOD(IllegalMoveSpdStatUpBuffCheck){
try{
player->AddBuff(BuffType::STAT_UP,5.f,1000.0_Pct,{"Move Spd %"});
Assert::Fail(L"Adding a Move Spd % buff succeeded! This should NOT be allowed!");
}catch(std::exception&e){}
}
TEST_METHOD(IllegalCritRateStatUpBuffCheck){ TEST_METHOD(IllegalCritRateStatUpBuffCheck){
try{ try{
player->AddBuff(BuffType::STAT_UP,5.f,1000.0_Pct,{"Crit Rate"}); player->AddBuff(BuffType::STAT_UP,5.f,1000.0_Pct,{"Crit Rate"});

@ -62,7 +62,7 @@ void Arrow::Update(float fElapsedTime){
} }
} }
void Arrow::PointToBestTargetPath(const uint8_t perceptionLevel){ const vf2d Arrow::PointToBestTargetPath(const uint8_t perceptionLevel){
if(perceptionLevel>90)ERR(std::format("WARNING! Perception level {} provided. Acceptable range is 0-90.",perceptionLevel)); if(perceptionLevel>90)ERR(std::format("WARNING! Perception level {} provided. Acceptable range is 0-90.",perceptionLevel));
Arrow copiedArrow{*this}; Arrow copiedArrow{*this};
float closestDist=std::numeric_limits<float>::max(); float closestDist=std::numeric_limits<float>::max();
@ -87,6 +87,7 @@ void Arrow::PointToBestTargetPath(const uint8_t perceptionLevel){
if(closestVel==vf2d{0,0})ERR("WARNING! We didn't find a valid path of flight for the Arrow! THIS SHOULD NOT BE HAPPENING!"); if(closestVel==vf2d{0,0})ERR("WARNING! We didn't find a valid path of flight for the Arrow! THIS SHOULD NOT BE HAPPENING!");
vel=closestVel; vel=closestVel;
return vel;
} }
BulletDestroyState Arrow::PlayerHit(Player*player) BulletDestroyState Arrow::PlayerHit(Player*player)

@ -74,7 +74,7 @@ struct Arrow:public Bullet{
void Update(float fElapsedTime)override; void Update(float fElapsedTime)override;
// Change the arrow's heading by predicting a path somewhere in the future and aiming at the closest possible spot to its targetPos. // Change the arrow's heading by predicting a path somewhere in the future and aiming at the closest possible spot to its targetPos.
// The perception level can be a value from 0-90 indicating the sweep angle to check beyond the initial aiming angle. // The perception level can be a value from 0-90 indicating the sweep angle to check beyond the initial aiming angle.
void PointToBestTargetPath(const uint8_t perceptionLevel); const vf2d PointToBestTargetPath(const uint8_t perceptionLevel);
BulletDestroyState PlayerHit(Player*player)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _PlayerHit()!! BulletDestroyState PlayerHit(Player*player)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _PlayerHit()!!
BulletDestroyState MonsterHit(Monster&monster)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!! BulletDestroyState MonsterHit(Monster&monster)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!!
}; };

@ -61,6 +61,7 @@ void Monster::STRATEGY::GOBLIN_BOW(Monster&m,float fElapsedTime,std::string stra
enum PhaseName{ enum PhaseName{
INITIALIZE_PERCEPTION, INITIALIZE_PERCEPTION,
MOVE, MOVE,
LOCKON,
WINDUP, WINDUP,
}; };
#pragma endregion #pragma endregion
@ -78,7 +79,7 @@ void Monster::STRATEGY::GOBLIN_BOW(Monster&m,float fElapsedTime,std::string stra
const bool outsideMaxShootingRange=distToPlayer>=ConfigPixelsArr("Stand Still and Shoot Range",1); const bool outsideMaxShootingRange=distToPlayer>=ConfigPixelsArr("Stand Still and Shoot Range",1);
auto PrepareToShoot=[&](){ auto PrepareToShoot=[&](){
m.phase=WINDUP; m.phase=LOCKON;
m.F(A::SHOOT_TIMER)=ConfigFloat("Attack Windup Time"); m.F(A::SHOOT_TIMER)=ConfigFloat("Attack Windup Time");
m.PerformAnimation("SHOOT",m.GetFacingDirectionToTarget(game->GetPlayer()->GetPos())); m.PerformAnimation("SHOOT",m.GetFacingDirectionToTarget(game->GetPlayer()->GetPos()));
@ -108,17 +109,23 @@ void Monster::STRATEGY::GOBLIN_BOW(Monster&m,float fElapsedTime,std::string stra
PrepareToShoot(); PrepareToShoot();
} }
}break; }break;
case WINDUP:{ case LOCKON:{
m.F(A::SHOOT_TIMER)-=fElapsedTime; m.F(A::SHOOT_TIMER)-=fElapsedTime;
m.UpdateFacingDirection(game->GetPlayer()->GetPos()); m.UpdateFacingDirection(game->GetPlayer()->GetPos());
if(m.F(A::SHOOT_TIMER)<=0){ if(m.F(A::SHOOT_TIMER)<=ConfigFloat("Bow Steadying Time")){
geom2d::line pointTowardsPlayer(m.GetPos(),game->GetPlayer()->GetPos()); geom2d::line pointTowardsPlayer(m.GetPos(),game->GetPlayer()->GetPos());
vf2d extendedLine=pointTowardsPlayer.upoint(1.1f); vf2d extendedLine=pointTowardsPlayer.upoint(1.1f);
CreateBullet(Arrow)(m.GetPos(),extendedLine,pointTowardsPlayer.vector().norm()*ConfigFloat("Arrow Spd"),"goblin_arrow.png",ConfigFloat("Arrow Hitbox Radius"),m.GetAttack(),m.OnUpperLevel())EndBullet; m.V(A::EXTENDED_LINE)=extendedLine;
Arrow&arrow=static_cast<Arrow&>(*BULLET_LIST.back()); Arrow tempArrow{m.GetPos(),extendedLine,pointTowardsPlayer.vector().norm()*ConfigFloat("Arrow Spd"),"goblin_arrow.png",ConfigFloat("Arrow Hitbox Radius"),m.GetAttack(),m.OnUpperLevel()};
arrow.PointToBestTargetPath(m.F(A::PERCEPTION_LEVEL)); m.V(A::FIRE_VELOCITY)=tempArrow.PointToBestTargetPath(m.F(A::PERCEPTION_LEVEL));
m.phase=WINDUP;
}
}break;
case WINDUP:{
m.F(A::SHOOT_TIMER)-=fElapsedTime;
if(m.F(A::SHOOT_TIMER)<=0){
m.F(A::ATTACK_COOLDOWN)=0.f; m.F(A::ATTACK_COOLDOWN)=0.f;
CreateBullet(Arrow)(m.GetPos(),m.V(A::EXTENDED_LINE),m.V(A::FIRE_VELOCITY),"goblin_arrow.png",ConfigFloat("Arrow Hitbox Radius"),m.GetAttack(),m.OnUpperLevel())EndBullet;
m.F(A::PERCEPTION_LEVEL)=std::min(ConfigFloat("Maximum Perception Level"),m.F(A::PERCEPTION_LEVEL)+ConfigFloat("Perception Level Increase")); m.F(A::PERCEPTION_LEVEL)=std::min(ConfigFloat("Maximum Perception Level"),m.F(A::PERCEPTION_LEVEL)+ConfigFloat("Perception Level Increase"));
m.PerformAnimation("IDLE",m.GetFacingDirectionToTarget(game->GetPlayer()->GetPos())); m.PerformAnimation("IDLE",m.GetFacingDirectionToTarget(game->GetPlayer()->GetPos()));
m.phase=MOVE; m.phase=MOVE;

@ -143,4 +143,6 @@ enum class Attribute{
STONE_TOSS_COUNT, STONE_TOSS_COUNT,
STONE_TOSS_TIMER, STONE_TOSS_TIMER,
SHOCKWAVE_COLOR, SHOCKWAVE_COLOR,
FIRE_VELOCITY,
EXTENDED_LINE,
}; };

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 1 #define VERSION_MAJOR 1
#define VERSION_MINOR 2 #define VERSION_MINOR 2
#define VERSION_PATCH 3 #define VERSION_PATCH 3
#define VERSION_BUILD 10186 #define VERSION_BUILD 10189
#define stringify(a) stringify_(a) #define stringify(a) stringify_(a)
#define stringify_(a) #a #define stringify_(a) #a

@ -599,6 +599,9 @@ MonsterStrategy
Arrow Hitbox Radius = 8 Arrow Hitbox Radius = 8
# How long the monster must stop turning their aim and lock in the target. The longer, the easier it is to dodge.
Bow Steadying Time = 0.33s
# When the monster will attempt to run away from target. # When the monster will attempt to run away from target.
Run Away Range = 500 Run Away Range = 500
# Chooses a random direction within the confines of this range, stays within it. # Chooses a random direction within the confines of this range, stays within it.

Loading…
Cancel
Save