Implemented Concussive Trap enchant.

pull/65/head
sigonasr2 3 months ago
parent 9005771f77
commit 60175a20d2
  1. 37
      Adventures in Lestoria Tests/EnchantTests.cpp
  2. 1
      Adventures in Lestoria Tests/ItemTests.cpp
  3. 1
      Adventures in Lestoria Tests/MonsterTests.cpp
  4. 1
      Adventures in Lestoria Tests/PlayerTests.cpp
  5. 104
      Adventures in Lestoria/AdventuresInLestoria.cpp
  6. 2
      Adventures in Lestoria/AdventuresInLestoria.h
  7. 1
      Adventures in Lestoria/Buff.h
  8. 2
      Adventures in Lestoria/BulletTypes.h
  9. 18
      Adventures in Lestoria/ExplosiveTrap.cpp
  10. 1
      Adventures in Lestoria/Player.cpp
  11. 4
      Adventures in Lestoria/Trapper.cpp
  12. 2
      Adventures in Lestoria/Version.h
  13. 1
      Adventures in Lestoria/Warrior.cpp

@ -974,5 +974,42 @@ namespace EnchantTests
}
Assert::AreEqual(size_t(1),newMonster.GetBuffs(BuffType::SPECIAL_MARK).size(),L"A special mark should spawned with the enchant.");
}
TEST_METHOD(ConcussiveTrapEnchantCheck){
testKey->bHeld=true; //Force the key to be held down for testing purposes.
game->ChangePlayerClass(TRAPPER);
player=game->GetPlayer();
player->SetPos({120,120});
player->CheckAndPerformAbility(player->GetAbility3(),testKeyboardInput);
game->SetElapsedTime(0.5f);
game->OnUserUpdate(0.5f);
Assert::AreEqual(size_t(1),BULLET_LIST.size(),L"An Explosive Trap now exists");
Monster&newMonster{game->SpawnMonster({},MONSTER_DATA["TestName"])};
game->OnUserUpdate(0.f);
BULLET_LIST.front()->MonsterHit(newMonster,newMonster.GetMarkStacks());
Assert::AreEqual(929,newMonster.GetHealth(),L"Monster takes 71 damage from an Explosive Trap normally.");
game->SetElapsedTime(5.5f);
game->OnUserUpdate(5.5f);
game->SetElapsedTime(5.5f);
game->OnUserUpdate(5.5f);
game->SetElapsedTime(0.5f);
game->OnUserUpdate(0.5f);
Assert::AreEqual(size_t(0),BULLET_LIST.size(),L"An Explosive Trap is gone.");
std::weak_ptr<Item>nullRing{Inventory::AddItem("Null Ring"s)};
Inventory::EquipItem(nullRing,EquipSlot::RING1);
nullRing.lock()->EnchantItem("Concussive Trap");
player->GetAbility3().charges=1;
player->CheckAndPerformAbility(player->GetAbility3(),testKeyboardInput);
game->SetElapsedTime(0.5f);
game->OnUserUpdate(0.5f);
Assert::AreEqual(size_t(1),BULLET_LIST.size(),L"An Explosive Trap now exists");
game->SetElapsedTime(5.5f);
game->OnUserUpdate(5.5f);
Assert::AreEqual(size_t(1),BULLET_LIST.size(),L"An Explosive Trap still exists (in the process of detonating a few times)");
Assert::AreEqual(721,newMonster.GetHealth(),L"Monster takes 104 + 104 damage from Concussive Trap bonus (Collision+Collateral Explosion).");
game->SetElapsedTime(5.5f);
game->OnUserUpdate(5.5f);
Assert::AreEqual(size_t(0),BULLET_LIST.size(),L"Explosive Trap detonates later.");
}
};
}

@ -79,6 +79,7 @@ namespace ItemTests
GameState::Initialize();
GameState::STATE=GameState::states.at(States::State::GAME_RUN);
testGame->ResetLevelStates();
#pragma region Setup a fake test map and test monster
game->MAP_DATA["CAMPAIGN_1_1"];
ItemDrop::ClearDrops();

@ -82,6 +82,7 @@ namespace MonsterTests
GameState::Initialize();
GameState::STATE=GameState::states.at(States::State::GAME_RUN);
testGame->ResetLevelStates();
#pragma region Setup a fake test map
game->MAP_DATA["CAMPAIGN_1_1"];

@ -88,6 +88,7 @@ namespace PlayerTests
MonsterData testMonsterData{"TestName","Test Monster",1000,10,5,{MonsterDropData{"Health Potion",100.f,1,1}},200.f};
MONSTER_DATA["TestName"]=testMonsterData;
#pragma endregion
testGame->ResetLevelStates();
player=testGame->GetPlayer();
//Setup key "0" as a test input

@ -188,7 +188,7 @@ AiL::AiL(bool testingMode){
void InitializeGameConfigurations(){
DATA.Reset();
utils::datafile::Read(DATA,"assets/config/configuration.txt");
utils::datafile::DEBUG_ACCESS_OPTIONS="debug_access_options"_I;
@ -2387,55 +2387,7 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
}
#pragma endregion
bossIndicatorPos.reset();
SPAWNER_LIST.clear();
SPAWNER_CONTROLLER={};
foregroundTileGroups.clear();
upperForegroundTileGroups.clear();
MONSTER_LIST.clear();
BULLET_LIST.clear();
DAMAGENUMBER_LIST.clear();
hudOverlay.Reset();
backgroundEffects.clear();
foregroundEffects.clear();
lockOnTargets.clear();
lockOnSpecialTargets.clear();
ItemDrop::drops.clear();
GameEvent::events.clear();
Audio::SetBGMPitch(1.f);
RepeatingSoundEffect::StopAllSounds();
#ifdef __EMSCRIPTEN__
Audio::muted=true;
Audio::UpdateBGMVolume();
#endif
zoomAdjustSpeed="Default Zoom Adjust Speed"_F;
targetZoom=1.f;
game->view.SetZoom(0.95f,game->view.WorldToScreen(game->camera.GetViewPosition()));
worldColor=WHITE;
worldColorFunc=[&](vi2d pos){return game->worldColor;};
levelTime=0;
bossName="";
bossDisplayTimer=0.f;
worldShakeTime=0.f;
encounterDuration=0;
totalDamageDealt=0;
encounterStarted=false;
totalBossEncounterMobs=0;
SetWindSpeed({});
Inventory::ResetLoadoutItemsUsed();
Input::StopVibration();
Input::SetLightbar({255,0,255});
GetPlayer()->hp=GetPlayer()->GetMaxHealth();
GetPlayer()->mana=GetPlayer()->GetMaxMana();
GetPlayer()->SetState(State::NORMAL);
GetPlayer()->GetCastInfo()={};
GetPlayer()->ResetAccumulatedXP();
GetPlayer()->_SetIframes(0.f);
GetPlayer()->SetInvisible(false);
GetPlayer()->ResetVelocity();
GetPlayer()->RemoveAllBuffs();
GetPlayer()->ResetTimers();
ResetLevelStates();
STEAMINPUT( //This is kind of a hack to refresh the in-game controls handle and button icons if for some reason it's not setup correctly.
Input::LoadSteamButtonIcons();
@ -4618,4 +4570,56 @@ void AiL::InitializeCamera(){
camera.SetMode(olc::utils::Camera2D::Mode::LazyFollow);
camera.SetWorldBoundary({0,0},GetCurrentMap().MapData.MapSize*GetCurrentMap().MapData.TileSize);
camera.EnableWorldBoundary(false);
}
void AiL::ResetLevelStates(){
bossIndicatorPos.reset();
SPAWNER_LIST.clear();
SPAWNER_CONTROLLER={};
foregroundTileGroups.clear();
upperForegroundTileGroups.clear();
MONSTER_LIST.clear();
BULLET_LIST.clear();
DAMAGENUMBER_LIST.clear();
hudOverlay.Reset();
backgroundEffects.clear();
foregroundEffects.clear();
lockOnTargets.clear();
lockOnSpecialTargets.clear();
ItemDrop::drops.clear();
GameEvent::events.clear();
Audio::SetBGMPitch(1.f);
RepeatingSoundEffect::StopAllSounds();
#ifdef __EMSCRIPTEN__
Audio::muted=true;
Audio::UpdateBGMVolume();
#endif
zoomAdjustSpeed="Default Zoom Adjust Speed"_F;
targetZoom=1.f;
game->view.SetZoom(0.95f,game->view.WorldToScreen(game->camera.GetViewPosition()));
worldColor=WHITE;
worldColorFunc=[&](vi2d pos){return game->worldColor;};
levelTime=0;
bossName="";
bossDisplayTimer=0.f;
worldShakeTime=0.f;
encounterDuration=0;
totalDamageDealt=0;
encounterStarted=false;
totalBossEncounterMobs=0;
SetWindSpeed({});
Inventory::ResetLoadoutItemsUsed();
Input::StopVibration();
Input::SetLightbar({255,0,255});
GetPlayer()->hp=GetPlayer()->GetMaxHealth();
GetPlayer()->mana=GetPlayer()->GetMaxMana();
GetPlayer()->SetState(State::NORMAL);
GetPlayer()->GetCastInfo()={};
GetPlayer()->ResetAccumulatedXP();
GetPlayer()->_SetIframes(0.f);
GetPlayer()->SetInvisible(false);
GetPlayer()->ResetVelocity();
GetPlayer()->RemoveAllBuffs();
GetPlayer()->ResetTimers();
}

@ -394,6 +394,8 @@ public:
void _SetCurrentLevel(const MapName map); //NOTE: This will modify the currentLevel variable without triggering anything else in-game, this will normally mess up the state in the game. Ideally this is only used when initializing a test level.
void InitializeCamera();
void ResetLevelStates();
std::vector<Effect*>GetForegroundEffects()const;
std::vector<Effect*>GetBackgroundEffects()const;
std::vector<Effect*>GetAllEffects()const; //Foreground and background effects in one vector.

@ -61,6 +61,7 @@ enum BuffType{
DAMAGE_AMPLIFICATION, //Multiplies all incoming damage by this amount.
LETHAL_TEMPO,
BURNING_ARROW_BURN,
SWORD_ENCHANTMENT,
};
enum class BuffRestorationType{
ONE_OFF, //This is used as a hack fix for the RestoreDuringCast Item script since they require us to restore 1 tick immediately. Over time buffs do not apply a tick immediately.

@ -318,6 +318,8 @@ private:
float automaticDetonationTime{};
float activationWaitTime{};
float lastBeepTime{};
int explosionCount{1};
float rearmTime{};
uint8_t beepCount{1U};
};

@ -47,7 +47,7 @@ INCLUDE_ANIMATION_DATA
INCLUDE_game
ExplosiveTrap::ExplosiveTrap(vf2d pos,float radius,float explosionRadius,float automaticDetonationTime,int damage,float fadeinTime,float fadeoutTime,float activationWaitTime,bool upperLevel,bool hitsMultiple,float lifetime,bool friendly,Pixel col,vf2d scale)
:activationWaitTime(activationWaitTime),automaticDetonationTime(automaticDetonationTime),activationRadius(radius),explosionRadius(explosionRadius),Bullet(pos,{},0.f,damage,"Ability Icons/explosive_trap.png",upperLevel,hitsMultiple,lifetime,false,friendly,col,scale,0.f,"Trap Hit"){
:activationWaitTime(activationWaitTime),automaticDetonationTime(automaticDetonationTime),activationRadius(radius),explosionRadius(explosionRadius),explosionCount(game->GetPlayer()->HasEnchant("Concussive Trap")?"Concussive Trap"_ENC["TRAP EXPLODE COUNT"]:1),Bullet(pos,{},0.f,damage,"Ability Icons/explosive_trap.png",upperLevel,hitsMultiple,INFINITE,false,friendly,col,scale,0.f,"Trap Hit"){
fadeInTime=fadeinTime;
animation.AddState("explosive_trap.png",ANIMATION_DATA["explosive_trap.png"]);
if(!friendly)ERR("WARNING! Trying to use unimplemented enemy version of the Explosive Trap Bullet!");
@ -58,7 +58,10 @@ void ExplosiveTrap::Update(float fElapsedTime){
if(IsDeactivated())return;
if(!trapActivated){
if(rearmTime>0.f){
rearmTime-=fElapsedTime;
if(rearmTime<=0.f)Detonate();
}else if(!trapActivated){
activationWaitTime-=fElapsedTime;
if(activationWaitTime<=0.f){
radius=activationRadius;
@ -89,8 +92,7 @@ BulletDestroyState ExplosiveTrap::PlayerHit(Player*player){
}
void ExplosiveTrap::Detonate(){
fadeOutTime=0.5f;
const HurtList list{game->HurtNotHit(pos,"Trapper.Ability 3.Explosion Radius"_F/100.f*24,damage,hitList,OnUpperLevel(),GetZ(),HurtType::MONSTER,HurtFlag::PLAYER_ABILITY)};
const HurtList list{game->Hurt(pos,"Trapper.Ability 3.Explosion Radius"_F/100.f*24,damage,OnUpperLevel(),GetZ(),HurtType::MONSTER,HurtFlag::PLAYER_ABILITY)};
for(const auto&[targetPtr,wasHit]:list){
if(wasHit){
std::get<Monster*>(targetPtr)->ApplyMark("Trapper.Ability 3.Explosion Mark Stack Time"_F,"Trapper.Ability 3.Explosion Mark Stack Increase"_I);
@ -103,7 +105,13 @@ void ExplosiveTrap::Detonate(){
explodeEffect->scaleSpd={0.125f,0.125f};
game->AddEffect(std::move(explodeEffect));
SoundEffect::PlaySFX("Explosion",pos);
Deactivate();
explosionCount--;
if(explosionCount>0)rearmTime=0.6f;
else{
fadeOutTime=0.5f;
Deactivate();
lifetime=0.f;
}
}
BulletDestroyState ExplosiveTrap::MonsterHit(Monster&monster,const uint8_t markStacksBeforeHit){

@ -335,6 +335,7 @@ float Player::GetSizeMult()const{
float Player::GetAttackRange(){
float finalAttackRange{base_attack_range};
if(HasEnchant("Adrenaline Stim")&&GetBuffs(BuffType::ADRENALINE_RUSH).size()>0)finalAttackRange+=base_attack_range*"Adrenaline Stim"_ENC["ATTACK RANGE INCREASE PCT"]/100.f;
if(GetBuffs(BuffType::SWORD_ENCHANTMENT).size()>0)finalAttackRange+=base_attack_range*"Sword Enchantment"_ENC["AUTO RANGE INCREASE"]/100.f;
finalAttackRange*=GetSizeMult();
return finalAttackRange;
}

@ -126,7 +126,9 @@ void Trapper::InitializeClassAbilities(){
#pragma region Trapper Ability 3 (Explosive Trap)
Trapper::ability3.action=
[](Player*p,vf2d pos={}){
CreateBullet(ExplosiveTrap)(p->GetPos(),"Trapper.Ability 3.Trap Radius"_I,"Trapper.Ability 3.Explosion Radius"_F/100.f*24,"Trapper.Ability 3.Trap Auto Detonate Time"_F,"Trapper.Ability 3.DamageMult"_F*p->GetAttack(),0.2f,0.5f,"Trapper.Ability 3.Trap Activation Time"_F,p->OnUpperLevel(),false,INFINITE,true,WHITE,{1.f,1.f})EndBullet;
float trapDamage{"Trapper.Ability 3.DamageMult"_F*p->GetAttack()};
if(p->HasEnchant("Concussive Trap"))trapDamage+=p->GetAttack()*"Concussive Trap"_ENC["ADDITIONAL EXPLOSION DAMAGE"]/100.f;
CreateBullet(ExplosiveTrap)(p->GetPos(),"Trapper.Ability 3.Trap Radius"_I,"Trapper.Ability 3.Explosion Radius"_F/100.f*24,"Trapper.Ability 3.Trap Auto Detonate Time"_F,trapDamage,0.2f,0.5f,"Trapper.Ability 3.Trap Activation Time"_F,p->OnUpperLevel(),false,INFINITE,true,WHITE,{1.f,1.f})EndBullet;
SoundEffect::PlaySFX("Place Down Trap",p->GetPos());
p->SetAnimationBasedOnTargetingDirection("SETTRAP",p->GetFacingDirection());
return true;

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

@ -168,6 +168,7 @@ void Warrior::InitializeClassAbilities(){
}
BULLET_LIST.push_back(std::make_unique<Bullet>(p->GetPos(),bulletVel,"Warrior.Ability 3.Radius"_F,p->GetAttack()*"Warrior.Ability 3.DamageMult"_F,"sonicslash.png",p->upperLevel,true,"Warrior.Ability 3.Lifetime"_F,true,true,WHITE,vf2d{"Warrior.Ability 3.Radius"_F/30,"Warrior.Ability 3.Radius"_F/30}));
game->SetupWorldShake("Warrior.Ability 3.ShakeTime"_F);
if(p->HasEnchant("Sword Enchantment"))p->AddBuff(BuffType::SWORD_ENCHANTMENT,"Sword Enchantment"_ENC["INCREASE DURATION"],1);
SoundEffect::PlaySFX("Warrior Sonic Slash",SoundEffect::CENTERED);
return true;
};

Loading…
Cancel
Save