Properly reset the player's health and mana between stages.

pull/28/head
sigonasr2 11 months ago
parent 668a5ca1b1
commit 52d36eab3b
  1. 6
      Crawler/AttributableStat.cpp
  2. 10
      Crawler/Crawler.cpp
  3. 14
      Crawler/Item.cpp
  4. 10
      Crawler/Monster.cpp
  5. 2
      Crawler/Monster.h
  6. 21
      Crawler/Player.cpp
  7. 14
      Crawler/Player.h
  8. 8
      Crawler/SlimeKing.cpp
  9. 2
      Crawler/TODO.txt
  10. 2
      Crawler/Version.h
  11. 100
      Crawler/assets/Campaigns/1_1_v2.tmx
  12. 3
      Crawler/config.h
  13. BIN
      x64/Release/Crawler.exe

@ -59,7 +59,7 @@ ItemAttributable&ItemAttributable::operator+=(ItemAttributable&rhs){
}; };
ItemAttribute::ItemAttribute(std::string_view name,bool isPct,std::string_view modifies) ItemAttribute::ItemAttribute(std::string_view name,bool isPct,std::string_view modifies)
:name(name),isPct(isPct),modifies(modifies){} :name(std::string(name)),isPct(isPct),modifies(std::string(modifies)){}
void ItemAttribute::Initialize(){ void ItemAttribute::Initialize(){
for(auto&[key,size]:DATA["Stats"]){ for(auto&[key,size]:DATA["Stats"]){
@ -73,7 +73,9 @@ void ItemAttribute::Initialize(){
} }
ItemAttribute&ItemAttribute::Get(const std::string_view name,const std::optional<std::variant<Player*,Monster*>>target){ ItemAttribute&ItemAttribute::Get(const std::string_view name,const std::optional<std::variant<Player*,Monster*>>target){
attributes.at(std::string(name)).target=target; if(target.has_value()){
attributes.at(std::string(name)).target=target;
}
return attributes.at(std::string(name)); return attributes.at(std::string(name));
} }
const std::string_view ItemAttribute::Name()const{ const std::string_view ItemAttribute::Name()const{

@ -201,6 +201,7 @@ bool Crawler::OnUserCreate(){
Inventory::AddItem("Bone Pants"); Inventory::AddItem("Bone Pants");
Inventory::AddItem("Bone Gloves"); Inventory::AddItem("Bone Gloves");
Inventory::AddItem("Elixir of Bear Strength",3); Inventory::AddItem("Elixir of Bear Strength",3);
Inventory::AddItem("Leather Helmet");
LoadLevel(LEVEL_NAMES["starting_map"_S]); LoadLevel(LEVEL_NAMES["starting_map"_S]);
ChangePlayerClass(WARRIOR); ChangePlayerClass(WARRIOR);
@ -1518,8 +1519,12 @@ void Crawler::LoadLevel(MapName map){
totalBossEncounterMobs=0; totalBossEncounterMobs=0;
Inventory::Clear("Monster Loot"); Inventory::Clear("Monster Loot");
Inventory::Clear("Stage Loot"); Inventory::Clear("Stage Loot");
std::cout<<GetPlayer()->hp<<std::endl;
GetPlayer()->hp=GetPlayer()->GetStat("Health");
GetPlayer()->mana=GetPlayer()->GetMaxMana();
GetPlayer()->SetState(State::NORMAL); GetPlayer()->SetState(State::NORMAL);
GetPlayer()->GetCastInfo()={}; GetPlayer()->GetCastInfo()={};
std::cout<<GetPlayer()->hp<<std::endl;
#pragma region Monster Spawn Data Setup #pragma region Monster Spawn Data Setup
for(auto&[key,value]:MAP_DATA[map].SpawnerData){ for(auto&[key,value]:MAP_DATA[map].SpawnerData){
@ -1835,6 +1840,7 @@ void Crawler::ChangePlayerClass(Class cl){
Ability itemAbility3=player->useItem3; Ability itemAbility3=player->useItem3;
uint32_t oldMoney=player->money; uint32_t oldMoney=player->money;
std::set<MenuComponent*>moneyListeners=Player::moneyListeners; std::set<MenuComponent*>moneyListeners=Player::moneyListeners;
EntityStats previousStats=player->stats;
switch(cl){ switch(cl){
case WARRIOR:{ case WARRIOR:{
player.reset(NEW Warrior(player.get())); player.reset(NEW Warrior(player.get()));
@ -1855,6 +1861,7 @@ void Crawler::ChangePlayerClass(Class cl){
player.reset(NEW Witch(player.get())); player.reset(NEW Witch(player.get()));
}break; }break;
} }
player->stats=previousStats;
player->SetBaseStat("Health",DATA.GetProperty(player->GetClassName()+".BaseHealth").GetInt()); player->SetBaseStat("Health",DATA.GetProperty(player->GetClassName()+".BaseHealth").GetInt());
player->hp=player->GetBaseStat("Health"); player->hp=player->GetBaseStat("Health");
player->SetBaseStat("Attack",DATA.GetProperty(player->GetClassName()+".BaseAtk").GetInt()); player->SetBaseStat("Attack",DATA.GetProperty(player->GetClassName()+".BaseAtk").GetInt());
@ -2000,6 +2007,9 @@ float operator ""_FRange(const char*key,std::size_t len){
Crawler::OutputDebugInfo(key,len); Crawler::OutputDebugInfo(key,len);
return float(util::random(float(DATA.GetProperty(std::string(key,len)).GetReal(1)-DATA.GetProperty(std::string(key,len)).GetReal(0)))+DATA.GetProperty(std::string(key,len)).GetReal(0)); return float(util::random(float(DATA.GetProperty(std::string(key,len)).GetReal(1)-DATA.GetProperty(std::string(key,len)).GetReal(0)))+DATA.GetProperty(std::string(key,len)).GetReal(0));
} }
float operator ""_Pct(long double pct){
return pct/100;
}
double operator ""_D(const char*key,std::size_t len){ double operator ""_D(const char*key,std::size_t len){
Crawler::OutputDebugInfo(key,len); Crawler::OutputDebugInfo(key,len);

@ -798,24 +798,24 @@ void Stats::InitializeDamageReductionTable(){
maxDamageReductionTable[0]=0; maxDamageReductionTable[0]=0;
for(int i=1;i<=1000;i++){ for(int i=1;i<=1000;i++){
if(i<=10){ if(i<=10){
totalReduction+=0.01; totalReduction+=1._Pct;
}else }else
if(i<=30){ if(i<=30){
totalReduction+=0.00'5; totalReduction+=0.5_Pct;
}else }else
if(i<=70){ if(i<=70){
totalReduction+=0.00'25; totalReduction+=0.25_Pct;
}else }else
if(i<=150){ if(i<=150){
totalReduction+=0.00'125; totalReduction+=0.125_Pct;
}else }else
if(i<=310){ if(i<=310){
totalReduction+=0.00'0625; totalReduction+=0.0625_Pct;
}else }else
if(i<=950){ if(i<=950){
totalReduction+=0.00'03125; totalReduction+=0.03125_Pct;
}else{ }else{
totalReduction+=0.00'1; totalReduction+=0.1_Pct;
} }
maxDamageReductionTable[i]=totalReduction; maxDamageReductionTable[i]=totalReduction;
} }

@ -60,7 +60,7 @@ safemap<std::string,std::function<void(Monster&,float,std::string)>>STRATEGY_DAT
std::map<std::string,Renderable*>MonsterData::imgs; std::map<std::string,Renderable*>MonsterData::imgs;
Monster::Monster(vf2d pos,MonsterData data,bool upperLevel,bool bossMob): Monster::Monster(vf2d pos,MonsterData data,bool upperLevel,bool bossMob):
pos(pos),maxhp(data.GetHealth()),size(data.GetSizeMult()),targetSize(data.GetSizeMult()),strategy(data.GetAIStrategy()),name(data.GetDisplayName()),upperLevel(upperLevel),isBoss(bossMob),facingDirection(DOWN){ pos(pos),hp(data.GetHealth()),size(data.GetSizeMult()),targetSize(data.GetSizeMult()),strategy(data.GetAIStrategy()),name(data.GetDisplayName()),upperLevel(upperLevel),isBoss(bossMob),facingDirection(DOWN){
bool firstAnimation=true; bool firstAnimation=true;
for(std::string&anim:data.GetAnimations()){ for(std::string&anim:data.GetAnimations()){
animation.AddState(anim,ANIMATION_DATA[anim]); animation.AddState(anim,ANIMATION_DATA[anim]);
@ -78,7 +78,7 @@ vf2d&Monster::GetPos(){
return pos; return pos;
} }
int Monster::GetHealth(){ int Monster::GetHealth(){
return stats.A("Health"); return hp;
} }
int Monster::GetAttack(){ int Monster::GetAttack(){
float mod_atk=float(stats.A("Attack")); float mod_atk=float(stats.A("Attack"));
@ -290,7 +290,7 @@ bool Monster::Hurt(int damage,bool onUpperLevel,float z){
mod_dmg-=damage*b.intensity; mod_dmg-=damage*b.intensity;
} }
mod_dmg=std::ceil(mod_dmg); mod_dmg=std::ceil(mod_dmg);
stats.A("Health")=std::max(0.f,stats.A("Health")-int(mod_dmg)); hp=std::max(0,hp-int(mod_dmg));
if(lastHitTimer>0){ if(lastHitTimer>0){
damageNumberPtr.get()->damage+=int(mod_dmg); damageNumberPtr.get()->damage+=int(mod_dmg);
damageNumberPtr.get()->pauseTime=0.4f; damageNumberPtr.get()->pauseTime=0.4f;
@ -302,7 +302,7 @@ bool Monster::Hurt(int damage,bool onUpperLevel,float z){
if(!IsAlive()){ if(!IsAlive()){
OnDeath(); OnDeath();
}else{ }else{
stats.A("Health")=std::max(1.f,stats.A("Health")); //Make sure it stays alive if it's supposed to be alive... hp=std::max(1,hp); //Make sure it stays alive if it's supposed to be alive...
} }
if(game->InBossEncounter()){ if(game->InBossEncounter()){
game->BossDamageDealt(int(mod_dmg)); game->BossDamageDealt(int(mod_dmg));
@ -313,7 +313,7 @@ bool Monster::Hurt(int damage,bool onUpperLevel,float z){
} }
bool Monster::IsAlive(){ bool Monster::IsAlive(){
return stats.A("Health")>0||!diesNormally; return hp>0||!diesNormally;
} }
vf2d&Monster::GetTargetPos(){ vf2d&Monster::GetTargetPos(){
return target; return target;

@ -165,7 +165,7 @@ private:
float friction=400; float friction=400;
vf2d target={0,0}; vf2d target={0,0};
float targetAcquireTimer=0; float targetAcquireTimer=0;
int maxhp; int hp;
ItemAttributable stats; ItemAttributable stats;
float size; float size;
float attackCooldownTimer=0; float attackCooldownTimer=0;

@ -48,6 +48,7 @@ All rights reserved.
#include "Menu.h" #include "Menu.h"
#include "GameState.h" #include "GameState.h"
#include "MenuComponent.h" #include "MenuComponent.h"
#include "config.h"
#include <string_view> #include <string_view>
@ -612,13 +613,13 @@ bool Player::Hurt(int damage,bool onUpperLevel,float z){
float finalPctDmgTaken=armorDmgTaken*otherDmgTaken; float finalPctDmgTaken=armorDmgTaken*otherDmgTaken;
if(finalPctDmgTaken<=0.06f){ if(finalPctDmgTaken<=6._Pct){
std::cout<<"WARNING! Damage Reduction has somehow ended up below 6%, which is over the cap!"<<std::endl; std::cout<<"WARNING! Damage Reduction has somehow ended up below 6%, which is over the cap!"<<std::endl;
} }
finalPctDmgTaken=std::max(0.0625f,finalPctDmgTaken);//Apply Damage Cap. finalPctDmgTaken=std::max(6.25_Pct,finalPctDmgTaken);//Apply Damage Cap.
float minPctDmgReduction=0.00'05f*GetStat("Defense"); float minPctDmgReduction=0.05_Pct*GetStat("Defense");
float finalPctDmgReduction=1-finalPctDmgTaken; float finalPctDmgReduction=1-finalPctDmgTaken;
float pctDmgReductionDiff=finalPctDmgReduction-minPctDmgReduction; float pctDmgReductionDiff=finalPctDmgReduction-minPctDmgReduction;
@ -935,27 +936,27 @@ void EntityStats::RecalculateEquipStats(){
component->OnEquipStatsUpdate(); component->OnEquipStatsUpdate();
} }
} }
const int&EntityStats::GetStat(ItemAttribute stat)const{ const float&EntityStats::GetStat(ItemAttribute stat)const{
return equipStats.A_Read(stat); return equipStats.A_Read(stat);
} }
const int&EntityStats::GetStat(std::string_view stat)const{ const float&EntityStats::GetStat(std::string_view stat)const{
return equipStats.A_Read(stat); return equipStats.A_Read(stat);
} }
const int&EntityStats::GetBaseStat(ItemAttribute stat)const{ const float&EntityStats::GetBaseStat(ItemAttribute stat)const{
return baseStats.A_Read(stat); return baseStats.A_Read(stat);
} }
const int&EntityStats::GetBaseStat(std::string_view stat)const{ const float&EntityStats::GetBaseStat(std::string_view stat)const{
return baseStats.A_Read(stat); return baseStats.A_Read(stat);
} }
void EntityStats::SetBaseStat(ItemAttribute stat,int val){ void EntityStats::SetBaseStat(ItemAttribute stat,float val){
baseStats.A(stat)=val; baseStats.A(stat)=val;
RecalculateEquipStats(); RecalculateEquipStats();
} }
void Player::SetBaseStat(std::string_view a,int val){ void Player::SetBaseStat(std::string_view a,float val){
stats.SetBaseStat(ItemAttribute::Get(a),val); stats.SetBaseStat(ItemAttribute::Get(a),val);
} }
void Player::SetBaseStat(ItemAttribute a,int val){ void Player::SetBaseStat(ItemAttribute a,float val){
stats.SetBaseStat(a,val); stats.SetBaseStat(a,val);
} }

@ -68,11 +68,11 @@ class EntityStats{
public: public:
void RecalculateEquipStats(); //Called when equipment is updated. void RecalculateEquipStats(); //Called when equipment is updated.
const ItemAttributable&GetStats()const; const ItemAttributable&GetStats()const;
const int&GetStat(ItemAttribute stat)const; //Get stats with equipment applied. const float&GetStat(ItemAttribute stat)const; //Get stats with equipment applied.
const int&GetStat(std::string_view stat)const; //Get stats with equipment applied. const float&GetStat(std::string_view stat)const; //Get stats with equipment applied.
const int&GetBaseStat(ItemAttribute stat)const; const float&GetBaseStat(ItemAttribute stat)const;
const int&GetBaseStat(std::string_view stat)const; const float&GetBaseStat(std::string_view stat)const;
void SetBaseStat(ItemAttribute a,int val); void SetBaseStat(ItemAttribute a,float val);
}; };
struct Player{ struct Player{
@ -102,8 +102,8 @@ public:
const int&GetStat(std::string_view a)const; const int&GetStat(std::string_view a)const;
const int&GetBaseStat(ItemAttribute a)const; const int&GetBaseStat(ItemAttribute a)const;
const int&GetBaseStat(std::string_view a)const; const int&GetBaseStat(std::string_view a)const;
void SetBaseStat(std::string_view a,int val); void SetBaseStat(std::string_view a,float val);
void SetBaseStat(ItemAttribute a,int val); void SetBaseStat(ItemAttribute a,float val);
const int GetMaxHealth()const; const int GetMaxHealth()const;
const int GetHealth()const; const int GetHealth()const;
const int GetMana()const; const int GetMana()const;

@ -240,7 +240,7 @@ void Monster::STRATEGY::SLIMEKING(Monster&m,float fElapsedTime,std::string strat
m.phase=ConfigInt("StartPhase"); m.phase=ConfigInt("StartPhase");
}break; }break;
case 1:{ case 1:{
if(m.stats.A("Health")<=m.maxhp*ConfigFloat("Phase2.Change")/100){ if(m.hp<=m.stats.A("Health")*ConfigFloat("Phase2.Change")/100){
m.phase=2; m.phase=2;
m.SetSize(ConfigFloat("Phase2.Size")/100,false); m.SetSize(ConfigFloat("Phase2.Size")/100,false);
TransitionPhase(m.phase); TransitionPhase(m.phase);
@ -273,7 +273,7 @@ void Monster::STRATEGY::SLIMEKING(Monster&m,float fElapsedTime,std::string strat
} }
}break; }break;
case 2:{ case 2:{
if(m.stats.A("Health")<=m.maxhp*ConfigFloat("Phase3.Change")/100){ if(m.hp<=m.stats.A("Health")*ConfigFloat("Phase3.Change")/100){
m.phase=3; m.phase=3;
m.SetSize(ConfigFloat("Phase3.Size")/100,false); m.SetSize(ConfigFloat("Phase3.Size")/100,false);
TransitionPhase(m.phase); TransitionPhase(m.phase);
@ -297,7 +297,7 @@ void Monster::STRATEGY::SLIMEKING(Monster&m,float fElapsedTime,std::string strat
} }
}break; }break;
case 3:{ case 3:{
if(m.stats.A("Health")<=m.maxhp*ConfigFloat("Phase4.Change")/100){ if(m.hp<=m.stats.A("Health")*ConfigFloat("Phase4.Change")/100){
m.phase=4; m.phase=4;
m.SetSize(ConfigFloat("Phase4.Size")/100,false); m.SetSize(ConfigFloat("Phase4.Size")/100,false);
m.AddBuff(BuffType::SLOWDOWN,99999,ConfigFloat("Phase4.MoveSpdModifier")/100); m.AddBuff(BuffType::SLOWDOWN,99999,ConfigFloat("Phase4.MoveSpdModifier")/100);
@ -325,7 +325,7 @@ void Monster::STRATEGY::SLIMEKING(Monster&m,float fElapsedTime,std::string strat
} }
}break; }break;
case 4:{ case 4:{
if(m.stats.A("Health")<=1){ //HP can't reach 0 when the dies normally flag is on. if(m.hp<=1){ //HP can't reach 0 when the dies normally flag is on.
m.phase=5; m.phase=5;
m.F(A::IFRAME_TIME_UPON_HIT)=1; m.F(A::IFRAME_TIME_UPON_HIT)=1;
m.I(A::HITS_UNTIL_DEATH)=int(m.GetSizeMult()*100/ConfigFloat("Phase5.SizeLossPerHit"))-1; m.I(A::HITS_UNTIL_DEATH)=int(m.GetSizeMult()*100/ConfigFloat("Phase5.SizeLossPerHit"))-1;

@ -1,6 +1,6 @@
January 1st January 1st
=========== ===========
Buff Item Script (Implement Other Stats) Buff Item Script (Implement Other Stats, Level Up Stats)
Sell Item Merchant Screen Sell Item Merchant Screen
Blacksmith Item Crafting Screen Blacksmith Item Crafting Screen
Randomized Item Stats Randomized Item Stats

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 0 #define VERSION_MAJOR 0
#define VERSION_MINOR 2 #define VERSION_MINOR 2
#define VERSION_PATCH 1 #define VERSION_PATCH 1
#define VERSION_BUILD 4643 #define VERSION_BUILD 4672
#define stringify(a) stringify_(a) #define stringify(a) stringify_(a)
#define stringify_(a) #a #define stringify_(a) #a

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.10.1" class="Map" orientation="orthogonal" renderorder="right-down" width="205" height="205" tilewidth="24" tileheight="24" infinite="0" backgroundcolor="#475500" nextlayerid="9" nextobjectid="149"> <map version="1.10" tiledversion="1.10.1" class="Map" orientation="orthogonal" renderorder="right-down" width="205" height="205" tilewidth="24" tileheight="24" infinite="0" backgroundcolor="#475500" nextlayerid="9" nextobjectid="163">
<properties> <properties>
<property name="Level Type" propertytype="LevelType" value="Dungeon"/> <property name="Level Type" propertytype="LevelType" value="Dungeon"/>
</properties> </properties>
@ -1971,5 +1971,103 @@
<point/> <point/>
</object> </object>
<object id="148" name="Player Spawn" type="PlayerSpawnLocation" x="624" y="4248" width="24" height="24"/> <object id="148" name="Player Spawn" type="PlayerSpawnLocation" x="624" y="4248" width="24" height="24"/>
<object id="149" name="Green Slime" type="Monster" x="1044" y="4254">
<properties>
<property name="Type" propertytype="MonsterName" value="Green Slime"/>
<property name="spawner" type="object" value="2"/>
</properties>
<point/>
</object>
<object id="150" name="Green Slime" type="Monster" x="1056" y="4350">
<properties>
<property name="Type" propertytype="MonsterName" value="Green Slime"/>
<property name="spawner" type="object" value="2"/>
</properties>
<point/>
</object>
<object id="151" name="Green Slime" type="Monster" x="1056" y="4386">
<properties>
<property name="Type" propertytype="MonsterName" value="Green Slime"/>
<property name="spawner" type="object" value="2"/>
</properties>
<point/>
</object>
<object id="152" name="Green Slime" type="Monster" x="1008" y="4290">
<properties>
<property name="Type" propertytype="MonsterName" value="Green Slime"/>
<property name="spawner" type="object" value="2"/>
</properties>
<point/>
</object>
<object id="153" name="Green Slime" type="Monster" x="1016" y="4322">
<properties>
<property name="Type" propertytype="MonsterName" value="Green Slime"/>
<property name="spawner" type="object" value="2"/>
</properties>
<point/>
</object>
<object id="154" name="Green Slime" type="Monster" x="1014" y="4242">
<properties>
<property name="Type" propertytype="MonsterName" value="Green Slime"/>
<property name="spawner" type="object" value="2"/>
</properties>
<point/>
</object>
<object id="155" name="Green Slime" type="Monster" x="1050" y="4218">
<properties>
<property name="Type" propertytype="MonsterName" value="Green Slime"/>
<property name="spawner" type="object" value="2"/>
</properties>
<point/>
</object>
<object id="156" name="Green Slime" type="Monster" x="1032" y="4338">
<properties>
<property name="Type" propertytype="MonsterName" value="Green Slime"/>
<property name="spawner" type="object" value="2"/>
</properties>
<point/>
</object>
<object id="157" name="Green Slime" type="Monster" x="1028" y="4364">
<properties>
<property name="Type" propertytype="MonsterName" value="Green Slime"/>
<property name="spawner" type="object" value="2"/>
</properties>
<point/>
</object>
<object id="158" name="Green Slime" type="Monster" x="1074" y="4272">
<properties>
<property name="Type" propertytype="MonsterName" value="Green Slime"/>
<property name="spawner" type="object" value="2"/>
</properties>
<point/>
</object>
<object id="159" name="Green Slime" type="Monster" x="1080" y="4314">
<properties>
<property name="Type" propertytype="MonsterName" value="Green Slime"/>
<property name="spawner" type="object" value="2"/>
</properties>
<point/>
</object>
<object id="160" name="Green Slime" type="Monster" x="1104" y="4350">
<properties>
<property name="Type" propertytype="MonsterName" value="Green Slime"/>
<property name="spawner" type="object" value="2"/>
</properties>
<point/>
</object>
<object id="161" name="Green Slime" type="Monster" x="1110" y="4278">
<properties>
<property name="Type" propertytype="MonsterName" value="Green Slime"/>
<property name="spawner" type="object" value="2"/>
</properties>
<point/>
</object>
<object id="162" name="Green Slime" type="Monster" x="1122" y="4308">
<properties>
<property name="Type" propertytype="MonsterName" value="Green Slime"/>
<property name="spawner" type="object" value="2"/>
</properties>
<point/>
</object>
</objectgroup> </objectgroup>
</map> </map>

@ -60,4 +60,5 @@ double operator ""_D(const char*key,std::size_t len);
utils::datafile operator ""_A(const char*key,std::size_t len); utils::datafile operator ""_A(const char*key,std::size_t len);
Pixel operator ""_Pixel(const char*key,std::size_t len); Pixel operator ""_Pixel(const char*key,std::size_t len);
float operator ""_FRange(const char*key,std::size_t len); float operator ""_FRange(const char*key,std::size_t len);
float operator ""_Pct(long double pct);

Binary file not shown.
Loading…
Cancel
Save