XP and level up systems implemented.

pull/28/head
sigonasr2 11 months ago
parent 2a72238e40
commit 4ac15dd1cc
  1. 2
      Crawler/CharacterMenuWindow.cpp
  2. 22
      Crawler/Crawler.cpp
  3. 1
      Crawler/Crawler.h
  4. 6
      Crawler/Monster.cpp
  5. 4
      Crawler/Monster.h
  6. 5
      Crawler/MonsterData.cpp
  7. 54
      Crawler/Player.cpp
  8. 16
      Crawler/Player.h
  9. 3
      Crawler/State_LevelComplete.cpp
  10. 2
      Crawler/Version.h
  11. 102
      Crawler/assets/Campaigns/1_1_v2.tmx
  12. 12
      Crawler/assets/config/Monsters.txt
  13. 107
      Crawler/assets/config/Player.txt
  14. 4
      Crawler/assets/config/classes/Ranger.txt
  15. 4
      Crawler/assets/config/classes/Warrior.txt
  16. 4
      Crawler/assets/config/classes/Wizard.txt
  17. BIN
      x64/Release/Crawler.exe

@ -165,7 +165,7 @@ void Menu::InitializeCharacterMenuWindow(){
RowItemDisplay*button=dynamic_cast<RowItemDisplay*>(data.component);
if(button!=nullptr){
const std::weak_ptr<Item>buttonItem=button->GetItem();
std::vector<int>statsBeforeEquip;
std::vector<float>statsBeforeEquip;
EquipSlot slot=EquipSlot(button->I(Attribute::EQUIP_TYPE));
for(const std::string&attribute:displayAttrs){
statsBeforeEquip.push_back(game->GetPlayer()->GetStat(attribute));

@ -175,6 +175,8 @@ bool Crawler::OnUserCreate(){
player=std::make_unique<Warrior>();
InitializePlayerLevelCap();
InitializeGraphics();
InitializeClasses();
@ -475,6 +477,9 @@ void Crawler::HandleUserInput(float fElapsedTime){
if(GetKey(O).bPressed){
ItemDrop::SpawnItem(&ITEM_DATA.at("Green Slime Remains"),player->GetPos(),player->OnUpperLevel());
}
if(GetKey(L).bHeld){
game->GetPlayer()->AddXP(1);
}
}
void Crawler::UpdateCamera(float fElapsedTime){
@ -1538,6 +1543,7 @@ void Crawler::LoadLevel(MapName map){
GetPlayer()->mana=GetPlayer()->GetMaxMana();
GetPlayer()->SetState(State::NORMAL);
GetPlayer()->GetCastInfo()={};
GetPlayer()->ResetAccumulatedXP();
#pragma region Monster Spawn Data Setup
for(auto&[key,value]:MAP_DATA[map].SpawnerData){
@ -1852,6 +1858,10 @@ void Crawler::ChangePlayerClass(Class cl){
Ability itemAbility2=player->useItem2;
Ability itemAbility3=player->useItem3;
uint32_t oldMoney=player->money;
uint8_t level=player->level;
uint8_t levelCap=player->levelCap;
uint32_t totalXPEarned=player->totalXPEarned;
uint32_t currentLevelXP=player->currentLevelXP;
std::set<MenuComponent*>moneyListeners=Player::moneyListeners;
EntityStats previousStats=player->stats;
switch(cl){
@ -1874,6 +1884,10 @@ void Crawler::ChangePlayerClass(Class cl){
player.reset(NEW Witch(player.get()));
}break;
}
player->level=level;
player->levelCap=levelCap;
player->totalXPEarned=totalXPEarned;
player->currentLevelXP=currentLevelXP;
player->stats=previousStats;
player->SetBaseStat("Health",DATA.GetProperty(player->GetClassName()+".BaseHealth").GetInt());
player->hp=player->GetBaseStat("Health");
@ -2501,4 +2515,12 @@ void Crawler::UpdateDiscordStatus(std::string levelName,std::string className){
}
}
#endif
}
void Crawler::InitializePlayerLevelCap(){
while(DATA["PlayerXP"].HasProperty(std::format("LEVEL[{}]",player->levelCap+1))){
player->levelCap++;
}
if(player->levelCap<=1)ERR("Could not detect level cap properly!")
std::cout<<"Level cap detected as "<<int(player->levelCap)<<std::endl;
}

@ -205,6 +205,7 @@ public:
bool GamePaused();
void EndGame();
void UpdateDiscordStatus(std::string levelName,std::string className);
void InitializePlayerLevelCap();
struct TileGroupData{
vi2d tilePos;

@ -474,6 +474,8 @@ void Monster::OnDeath(){
}
}
}
game->GetPlayer()->AddAccumulatedXP(MONSTER_DATA.at(name).GetXP());
}
const ItemAttributable&Monster::GetStats()const{
@ -482,4 +484,8 @@ const ItemAttributable&Monster::GetStats()const{
ItemAttribute&Monster::Get(std::string_view attr){
return ItemAttribute::Get(attr,this);
}
const uint32_t MonsterData::GetXP()const{
return xp;
}

@ -75,6 +75,7 @@ struct MonsterData{
std::string name;
int hp;
int atk;
uint32_t xp;
float moveSpd;//1.0=100%
float size;
std::vector<std::string> animations;
@ -86,9 +87,10 @@ struct MonsterData{
std::vector<MonsterDropData> dropData;
public:
MonsterData();
MonsterData(std::string name,int hp,int atk,std::vector<std::string>animations,std::vector<MonsterDropData>drops,float moveSpd=1.0f,float size=1.0f,std::string strategy="Run Towards",int collisionDmg=0);
MonsterData(std::string name,int hp,int atk,const uint32_t xp,std::vector<std::string>animations,std::vector<MonsterDropData>drops,float moveSpd=1.0f,float size=1.0f,std::string strategy="Run Towards",int collisionDmg=0);
int GetHealth();
int GetAttack();
const uint32_t GetXP()const;
float GetMoveSpdMult();
float GetSizeMult();
std::string GetAIStrategy();

@ -52,8 +52,8 @@ std::map<std::string,MonsterData>MONSTER_DATA;
MonsterData::MonsterData()
:atk(0),collisionDmg(0),hp(0),moveSpd(0),size(0),strategy("Run Towards"){}
MonsterData::MonsterData(std::string name,int hp,int atk,std::vector<std::string>animations,std::vector<MonsterDropData>drops,float moveSpd,float size,std::string strategy,int collisionDmg):
name(name),hp(hp),atk(atk),moveSpd(moveSpd),size(size),strategy(strategy),animations(animations),dropData(drops),collisionDmg(collisionDmg){}
MonsterData::MonsterData(std::string name,int hp,int atk,const uint32_t xp,std::vector<std::string>animations,std::vector<MonsterDropData>drops,float moveSpd,float size,std::string strategy,int collisionDmg):
name(name),hp(hp),atk(atk),xp(xp),moveSpd(moveSpd),size(size),strategy(strategy),animations(animations),dropData(drops),collisionDmg(collisionDmg){}
void MonsterData::InitializeMonsterData(){
for(auto&[key,size]:DATA["Monsters"].GetKeys()){
@ -148,6 +148,7 @@ void MonsterData::InitializeMonsterData(){
MonsterName,
DATA["Monsters"][MonsterName]["Health"].GetInt(),
DATA["Monsters"][MonsterName]["Attack"].GetInt(),
DATA["Monsters"][MonsterName]["XP"].GetInt(),
animations,
drops,
float(DATA["Monsters"][MonsterName]["MoveSpd"].GetReal())/100,

@ -51,7 +51,6 @@ All rights reserved.
#include "config.h"
#include <string_view>
INCLUDE_MONSTER_DATA
INCLUDE_MONSTER_LIST
INCLUDE_ANIMATION_DATA
@ -958,6 +957,9 @@ void EntityStats::SetBaseStat(ItemAttribute stat,float val){
baseStats.A(stat)=val;
RecalculateEquipStats();
}
void EntityStats::SetBaseStat(std::string_view stat,float val){
SetBaseStat(ItemAttribute::Get(stat),val);
}
void Player::SetBaseStat(std::string_view a,float val){
stats.SetBaseStat(ItemAttribute::Get(a),val);
}
@ -1089,4 +1091,54 @@ const float Player::GetDamageReductionPct()const{
float modDmgReductionPct=0;
modDmgReductionPct+=GetStat("Damage Reduction")/100;
return modDmgReductionPct;
}
void Player::AddXP(const uint32_t xpGain){
currentLevelXP+=xpGain;
totalXPEarned+=xpGain;
uint32_t nextLevelXP=NextLevelXPRequired();
if(Level()<LevelCap()){
if(currentLevelXP>nextLevelXP){
currentLevelXP-=nextLevelXP;
level++;
OnLevelUp();
}
}
}
void Player::OnLevelUp(){
stats.SetBaseStat("Health",GetBaseStat("Health")+hpGrowthRate);
stats.SetBaseStat("Attack",GetBaseStat("Attack")+atkGrowthRate);
Heal(GetBaseStat("Health"));
}
const uint8_t Player::LevelCap()const{
return levelCap;
}
const uint8_t Player::Level()const{
return level;
}
const uint32_t Player::CurrentXP()const{
return currentLevelXP;
}
const uint32_t Player::TotalXP()const{
return totalXPEarned;
}
const uint32_t Player::NextLevelXPRequired()const{
if(Level()<LevelCap()){
return DATA.GetProperty(std::format("PlayerXP.LEVEL[{}]",Level()+1)).GetInt();
}
return 0;
}
void Player::ResetAccumulatedXP(){
accumulatedXP=0;
}
void Player::AddAccumulatedXP(const uint32_t xpGain){
accumulatedXP+=xpGain;
}
const uint32_t Player::GetAccumulatedXP()const{
return accumulatedXP;
}

@ -73,6 +73,7 @@ public:
const float&GetBaseStat(ItemAttribute stat)const;
const float&GetBaseStat(std::string_view stat)const;
void SetBaseStat(ItemAttribute a,float val);
void SetBaseStat(std::string_view a,float val);
};
struct Player{
@ -209,15 +210,30 @@ public:
static void AddMoneyListener(MenuComponent*component);
uint32_t GetMoney()const;
void SetMoney(uint32_t newMoney);
void AddXP(const uint32_t xpGain);
void OnLevelUp();
const uint8_t LevelCap()const;
const uint8_t Level()const;
const uint32_t CurrentXP()const;
const uint32_t TotalXP()const;
const uint32_t NextLevelXPRequired()const;
void CancelCast();
const ItemAttributable&GetStats()const;
void ResetAccumulatedXP();
const uint32_t GetAccumulatedXP()const;
void AddAccumulatedXP(const uint32_t xpGain);
private:
int hp="Warrior.BaseHealth"_I;
int mana="Player.BaseMana"_I,maxmana=mana;
float hpGrowthRate="Warrior.HealthGrowthRate"_F;
float atkGrowthRate="Warrior.AtkGrowthRate"_F;
vf2d pos;
uint8_t level=1;
uint8_t levelCap=1;
uint32_t totalXPEarned=0;
uint32_t currentLevelXP=0;
uint32_t accumulatedXP=0;
float z=0;
float size=1.0f;
float spin_attack_timer=0;

@ -39,6 +39,7 @@ All rights reserved.
#include "Crawler.h"
#include "DEFINES.h"
#include "Menu.h"
#include "MenuLabel.h"
INCLUDE_MONSTER_LIST
INCLUDE_game
@ -47,6 +48,8 @@ void State_LevelComplete::OnStateChange(GameState*prevState){
if(Menu::IsMenuOpen()){
Menu::CloseAllMenus();
}
Component<MenuLabel>(MenuType::LEVEL_COMPLETE,"Level EXP Gain Outline")->SetLabel(std::format("+{} Exp",game->GetPlayer()->GetAccumulatedXP()));
game->GetPlayer()->AddXP(game->GetPlayer()->GetAccumulatedXP());
game->GetPlayer()->SetState(State::NORMAL);
Menu::OpenMenu(LEVEL_COMPLETE);
};

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

@ -1,5 +1,5 @@
<?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="163">
<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="164">
<properties>
<property name="Level Type" propertytype="LevelType" value="Dungeon"/>
</properties>
@ -1280,13 +1280,6 @@
<object id="2" name="Spawn Group 1" type="SpawnGroup" x="870" y="4008" width="558.667" height="576">
<ellipse/>
</object>
<object id="3" name="Green Slime" type="Monster" x="1103.33" y="4220">
<properties>
<property name="Type" propertytype="MonsterName" value="Green Slime"/>
<property name="spawner" type="object" value="2"/>
</properties>
<point/>
</object>
<object id="4" name="Green Slime" type="Monster" x="1052" y="4304">
<properties>
<property name="Type" propertytype="MonsterName" value="Green Slime"/>
@ -1294,13 +1287,6 @@
</properties>
<point/>
</object>
<object id="5" name="Green Slime" type="Monster" x="1087.33" y="4427.33">
<properties>
<property name="Type" propertytype="MonsterName" value="Green Slime"/>
<property name="spawner" type="object" value="2"/>
</properties>
<point/>
</object>
<object id="6" name="Spawn Group 2" type="SpawnGroup" x="1590" y="4020" width="521.333" height="534.667">
<ellipse/>
</object>
@ -1970,21 +1956,6 @@
</properties>
<point/>
</object>
<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"/>
@ -1992,27 +1963,6 @@
</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"/>
@ -2020,54 +1970,6 @@
</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>
<object id="163" name="Player Spawn" type="PlayerSpawnLocation" x="4674" y="2256" width="24" height="24"/>
</objectgroup>
</map>

@ -10,6 +10,8 @@ Monsters
MoveSpd = 110
Size = 80
XP = 5
Strategy = Run Towards
BumpStopChance = 2
@ -40,6 +42,8 @@ Monsters
MoveSpd = 80
Size = 100
XP = 7
Strategy = Shoot Afar
#Size of each animation frame
@ -68,6 +72,8 @@ Monsters
MoveSpd = 95
Size = 120
XP = 7
Strategy = Run Towards
#Size of each animation frame
@ -96,6 +102,8 @@ Monsters
MoveSpd = 40
Size = 160
XP = 20
Strategy = Run Towards
#Size of each animation frame
@ -123,6 +131,8 @@ Monsters
MoveSpd = 0
Size = 100
XP = 8
Strategy = Turret
#Size of each animation frame
@ -151,6 +161,8 @@ Monsters
MoveSpd = 100
Size = 800
XP = 250
Strategy = Slime King
StartPhase = 1

@ -39,4 +39,109 @@ Player
PLAYER_ANIMATION[9] = WIZARD_ATTACK
PLAYER_ANIMATION[10] = WIZARD_CAST
PLAYER_ANIMATION[11] = WIZARD_IDLE
}
}
PlayerXP
{
LEVEL[1] = 100xp
LEVEL[2] = 200xp
LEVEL[3] = 300xp
LEVEL[4] = 400xp
LEVEL[5] = 500xp
LEVEL[6] = 600xp
LEVEL[7] = 700xp
LEVEL[8] = 800xp
LEVEL[9] = 900xp
LEVEL[10] = 1000xp
LEVEL[11] = 1100xp
LEVEL[12] = 1200xp
LEVEL[13] = 1300xp
LEVEL[14] = 1400xp
LEVEL[15] = 1500xp
LEVEL[16] = 1600xp
LEVEL[17] = 1700xp
LEVEL[18] = 1800xp
LEVEL[19] = 1900xp
LEVEL[20] = 2000xp
LEVEL[21] = 2100xp
LEVEL[22] = 2200xp
LEVEL[23] = 2300xp
LEVEL[24] = 2400xp
LEVEL[25] = 2500xp
LEVEL[26] = 2600xp
LEVEL[27] = 2700xp
LEVEL[28] = 2800xp
LEVEL[29] = 2900xp
LEVEL[30] = 3000xp
LEVEL[31] = 3100xp
LEVEL[32] = 3200xp
LEVEL[33] = 3300xp
LEVEL[34] = 3400xp
LEVEL[35] = 3500xp
LEVEL[36] = 3600xp
LEVEL[37] = 3700xp
LEVEL[38] = 3800xp
LEVEL[39] = 3900xp
LEVEL[40] = 4000xp
LEVEL[41] = 4100xp
LEVEL[42] = 4200xp
LEVEL[43] = 4300xp
LEVEL[44] = 4400xp
LEVEL[45] = 4500xp
LEVEL[46] = 4600xp
LEVEL[47] = 4700xp
LEVEL[48] = 4800xp
LEVEL[49] = 4900xp
LEVEL[50] = 5000xp
LEVEL[51] = 5100xp
LEVEL[52] = 5200xp
LEVEL[53] = 5300xp
LEVEL[54] = 5400xp
LEVEL[55] = 5500xp
LEVEL[56] = 5600xp
LEVEL[57] = 5700xp
LEVEL[58] = 5800xp
LEVEL[59] = 5900xp
LEVEL[60] = 6000xp
LEVEL[61] = 6100xp
LEVEL[62] = 6200xp
LEVEL[63] = 6300xp
LEVEL[64] = 6400xp
LEVEL[65] = 6500xp
LEVEL[66] = 6600xp
LEVEL[67] = 6700xp
LEVEL[68] = 6800xp
LEVEL[69] = 6900xp
LEVEL[70] = 7000xp
LEVEL[71] = 7100xp
LEVEL[72] = 7200xp
LEVEL[73] = 7300xp
LEVEL[74] = 7400xp
LEVEL[75] = 7500xp
LEVEL[76] = 7600xp
LEVEL[77] = 7700xp
LEVEL[78] = 7800xp
LEVEL[79] = 7900xp
LEVEL[80] = 8000xp
LEVEL[81] = 8100xp
LEVEL[82] = 8200xp
LEVEL[83] = 8300xp
LEVEL[84] = 8400xp
LEVEL[85] = 8500xp
LEVEL[86] = 8600xp
LEVEL[87] = 8700xp
LEVEL[88] = 8800xp
LEVEL[89] = 8900xp
LEVEL[90] = 9000xp
LEVEL[91] = 9100xp
LEVEL[92] = 9200xp
LEVEL[93] = 9300xp
LEVEL[94] = 9400xp
LEVEL[95] = 9500xp
LEVEL[96] = 9600xp
LEVEL[97] = 9700xp
LEVEL[98] = 9800xp
LEVEL[99] = 9900xp
LEVEL[100] = 10000xp
}

@ -6,9 +6,9 @@ Ranger
BaseAtk = 13
# Amount of health gained per level.
HealthGrowthRate = 3
HealthGrowthRate = 7
# Amount of attack gained per level.
AtkGrowthRate = 0.8
AtkGrowthRate = 3
FullRender = unknown_full_render.png

@ -6,9 +6,9 @@ Warrior
BaseAtk = 10
# Amount of health gained per level.
HealthGrowthRate = 5
HealthGrowthRate = 9
# Amount of attack gained per level.
AtkGrowthRate = 0.2
AtkGrowthRate = 2
FullRender = knight_full_render1.png

@ -6,9 +6,9 @@ Wizard
BaseAtk = 15
# Amount of health gained per level.
HealthGrowthRate = 1
HealthGrowthRate = 5
# Amount of attack gained per level.
AtkGrowthRate = 0.5
AtkGrowthRate = 4
FullRender = wizard_full_render.png

Binary file not shown.
Loading…
Cancel
Save