Setup King Slime encounter, Boss room map setup with spawn and player, made non-infinite. Implemented enemy iframes and added phase framework for the boss.
This commit is contained in:
parent
c9fa25a823
commit
c75e56d642
@ -129,7 +129,7 @@ bool Crawler::OnUserCreate(){
|
||||
sig::Animation::SetupPlayerAnimations();
|
||||
view=TileTransformedView{GetScreenSize(),{1,1}};
|
||||
|
||||
LoadLevel(CAMPAIGN_1_1);
|
||||
LoadLevel(BOSS_1);
|
||||
InitializeClasses();
|
||||
ChangePlayerClass(WARRIOR);
|
||||
Warrior::ability4=Ranger::ability1; //Class ability swapping demonstration.
|
||||
@ -1180,78 +1180,65 @@ int main()
|
||||
}
|
||||
|
||||
datafilestringdata operator ""_s(const char*key,std::size_t len){
|
||||
if(utils::datafile::DEBUG_ACCESS_OPTIONS){
|
||||
std::cout<<"Reading "<<std::string(key,len)<<std::endl;
|
||||
}
|
||||
Crawler::OutputDebugInfo(key,len);
|
||||
return {DATA,std::string(key,len)};
|
||||
}
|
||||
|
||||
datafileintdata operator ""_i(const char*key,std::size_t len){
|
||||
if(utils::datafile::DEBUG_ACCESS_OPTIONS){
|
||||
std::cout<<"Reading "<<std::string(key,len)<<std::endl;
|
||||
}
|
||||
Crawler::OutputDebugInfo(key,len);
|
||||
return {DATA,std::string(key,len)};
|
||||
}
|
||||
|
||||
datafilefloatdata operator ""_f(const char*key,std::size_t len){
|
||||
if(utils::datafile::DEBUG_ACCESS_OPTIONS){
|
||||
std::cout<<"Reading "<<std::string(key,len)<<std::endl;
|
||||
}
|
||||
Crawler::OutputDebugInfo(key,len);
|
||||
return {DATA,std::string(key,len)};
|
||||
}
|
||||
|
||||
datafiledoubledata operator ""_d(const char*key,std::size_t len){
|
||||
if(utils::datafile::DEBUG_ACCESS_OPTIONS){
|
||||
std::cout<<"Reading "<<std::string(key,len)<<std::endl;
|
||||
}
|
||||
Crawler::OutputDebugInfo(key,len);
|
||||
return {DATA,std::string(key,len)};
|
||||
}
|
||||
|
||||
Pixel operator ""_Pixel(const char*key,std::size_t len){
|
||||
if(utils::datafile::DEBUG_ACCESS_OPTIONS){
|
||||
std::cout<<"Reading "<<std::string(key,len)<<std::endl;
|
||||
}
|
||||
Crawler::OutputDebugInfo(key,len);
|
||||
return {uint8_t(DATA.GetProperty(std::string(key,len)).GetInt(0)),uint8_t(DATA.GetProperty(std::string(key,len)).GetInt(1)),uint8_t(DATA.GetProperty(std::string(key,len)).GetInt(2)),uint8_t(DATA.GetProperty(std::string(key,len)).GetInt(3))};
|
||||
}
|
||||
|
||||
std::string operator ""_S(const char*key,std::size_t len){
|
||||
if(utils::datafile::DEBUG_ACCESS_OPTIONS){
|
||||
std::cout<<"Reading "<<std::string(key,len)<<std::endl;
|
||||
}
|
||||
Crawler::OutputDebugInfo(key,len);
|
||||
return DATA.GetProperty(std::string(key,len)).GetString();
|
||||
}
|
||||
|
||||
int operator ""_I(const char*key,std::size_t len){
|
||||
if(utils::datafile::DEBUG_ACCESS_OPTIONS){
|
||||
std::cout<<"Reading "<<std::string(key,len)<<std::endl;
|
||||
}
|
||||
Crawler::OutputDebugInfo(key,len);
|
||||
return DATA.GetProperty(std::string(key,len)).GetInt();
|
||||
}
|
||||
|
||||
float operator ""_F(const char*key,std::size_t len){
|
||||
if(utils::datafile::DEBUG_ACCESS_OPTIONS){
|
||||
std::cout<<"Reading "<<std::string(key,len)<<std::endl;
|
||||
}
|
||||
Crawler::OutputDebugInfo(key,len);
|
||||
return DATA.GetProperty(std::string(key,len)).GetReal();
|
||||
}
|
||||
|
||||
float operator ""_FRange(const char*key,std::size_t len){
|
||||
if(utils::datafile::DEBUG_ACCESS_OPTIONS){
|
||||
std::cout<<"Reading "<<std::string(key,len)<<std::endl;
|
||||
}
|
||||
Crawler::OutputDebugInfo(key,len);
|
||||
return util::random(DATA.GetProperty(std::string(key,len)).GetReal(1)-DATA.GetProperty(std::string(key,len)).GetReal(0))+DATA.GetProperty(std::string(key,len)).GetReal(0);
|
||||
}
|
||||
|
||||
double operator ""_D(const char*key,std::size_t len){
|
||||
if(utils::datafile::DEBUG_ACCESS_OPTIONS){
|
||||
std::cout<<std::string(key,len)<<std::endl;
|
||||
}
|
||||
Crawler::OutputDebugInfo(key,len);
|
||||
return DATA.GetProperty(std::string(key,len)).GetReal();
|
||||
}
|
||||
|
||||
datafile operator ""_A(const char*key,std::size_t len){
|
||||
if(utils::datafile::DEBUG_ACCESS_OPTIONS){
|
||||
std::cout<<std::string(key,len)<<std::endl;
|
||||
}
|
||||
Crawler::OutputDebugInfo(key,len);
|
||||
return DATA.GetProperty(std::string(key,len));
|
||||
}
|
||||
|
||||
void Crawler::OutputDebugInfo(const char*key,std::size_t len){
|
||||
if(utils::datafile::DEBUG_ACCESS_OPTIONS){
|
||||
std::string k=std::string(key);
|
||||
if(!k.starts_with("debug_")){
|
||||
std::cout<<"Reading "<<k<<std::endl;
|
||||
}
|
||||
}
|
||||
}
|
@ -107,4 +107,5 @@ public:
|
||||
datafilefloatdata GetFloatList(std::string key);
|
||||
double GetDouble(std::string key);
|
||||
datafiledoubledata GetDoubleList(std::string key);
|
||||
static void OutputDebugInfo(const char*key,std::size_t len);
|
||||
};
|
||||
|
@ -123,7 +123,8 @@
|
||||
"Blue Slime",
|
||||
"Red Slime",
|
||||
"Yellow Slime",
|
||||
"Flower Turret"
|
||||
"Flower Turret",
|
||||
"Slime King"
|
||||
],
|
||||
"valuesAsFlags": false
|
||||
},
|
||||
|
@ -10,6 +10,7 @@
|
||||
#define INCLUDE_EMITTER_LIST extern std::vector<std::unique_ptr<Emitter>>EMITTER_LIST;
|
||||
#define INCLUDE_DATA extern utils::datafile DATA;
|
||||
#define INCLUDE_STRATEGY_DATA extern safemap<std::string,int>STRATEGY_DATA;
|
||||
#define INCLUDE_STRATEGY_ID_DATA extern safemap<std::string,int>STRATEGY_ID_DATA;
|
||||
|
||||
#define ACCESS_PLAYER Player*p=game->GetPlayer();
|
||||
|
||||
|
@ -16,6 +16,7 @@ INCLUDE_DATA
|
||||
INCLUDE_STRATEGY_DATA
|
||||
|
||||
safemap<std::string,int>STRATEGY_DATA;
|
||||
safemap<int,std::string>STRATEGY_ID_DATA;
|
||||
std::map<int,Renderable*>MonsterData::imgs;
|
||||
|
||||
Monster::Monster(vf2d pos,MonsterData data,bool upperLevel):
|
||||
@ -108,6 +109,7 @@ bool Monster::SetY(float y){
|
||||
}
|
||||
bool Monster::Update(float fElapsedTime){
|
||||
lastHitTimer=std::max(0.f,lastHitTimer-fElapsedTime);
|
||||
iframe_timer=std::max(0.f,iframe_timer-fElapsedTime);
|
||||
if(IsAlive()){
|
||||
for(std::vector<Buff>::iterator it=buffList.begin();it!=buffList.end();++it){
|
||||
Buff&b=*it;
|
||||
@ -160,7 +162,7 @@ bool Monster::Update(float fElapsedTime){
|
||||
SetY(pos.y+vel.y*fElapsedTime);
|
||||
}
|
||||
}
|
||||
if(hp<=0){
|
||||
if(!IsAlive()){
|
||||
deathTimer+=fElapsedTime;
|
||||
if(deathTimer>3){
|
||||
return false;
|
||||
@ -227,7 +229,7 @@ std::string Monster::GetDeathAnimationName(){
|
||||
return MONSTER_DATA[id].GetDeathAnimation();
|
||||
}
|
||||
bool Monster::Hurt(int damage,bool onUpperLevel){
|
||||
if(hp<=0||onUpperLevel!=OnUpperLevel()||HasIframes()) return false;
|
||||
if(!IsAlive()||onUpperLevel!=OnUpperLevel()||HasIframes()) return false;
|
||||
float mod_dmg=damage;
|
||||
for(Buff&b:GetBuffs(BuffType::DAMAGE_REDUCTION)){
|
||||
mod_dmg-=damage*b.intensity;
|
||||
@ -242,14 +244,17 @@ bool Monster::Hurt(int damage,bool onUpperLevel){
|
||||
damageNumberPtr=numb;
|
||||
}
|
||||
lastHitTimer=0.05;
|
||||
if(hp<=0){
|
||||
if(!IsAlive()){
|
||||
animation.ChangeState(internal_animState,GetDeathAnimationName());
|
||||
}
|
||||
if(GetStrategy()=="Slime King"&&phase==5){
|
||||
iframe_timer=iframeTimeUponHit;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Monster::IsAlive(){
|
||||
return hp>0;
|
||||
return hp>0||!diesNormally;
|
||||
}
|
||||
vf2d&Monster::GetTargetPos(){
|
||||
return target;
|
||||
@ -341,10 +346,13 @@ void Monster::SetState(State newState){
|
||||
void Monster::InitializeStrategies(){
|
||||
int readCounter=0;
|
||||
while(DATA["MonsterStrategy"].HasProperty(std::to_string(readCounter))){
|
||||
STRATEGY_DATA[DATA["MonsterStrategy"][std::to_string(readCounter)]["Name"].GetString()]=readCounter;
|
||||
std::string strategyName=DATA["MonsterStrategy"][std::to_string(readCounter)]["Name"].GetString();
|
||||
STRATEGY_DATA[strategyName]=readCounter;
|
||||
STRATEGY_ID_DATA[readCounter]=strategyName;
|
||||
readCounter++;
|
||||
}
|
||||
STRATEGY_DATA.SetInitialized();
|
||||
STRATEGY_ID_DATA.SetInitialized();
|
||||
}
|
||||
|
||||
bool Monster::HasIframes(){
|
||||
@ -353,4 +361,8 @@ bool Monster::HasIframes(){
|
||||
|
||||
float Monster::GetZ(){
|
||||
return z;
|
||||
}
|
||||
|
||||
std::string Monster::GetStrategy(){
|
||||
return STRATEGY_ID_DATA[strategy];
|
||||
}
|
@ -85,6 +85,9 @@ private:
|
||||
int pathIndex=0;
|
||||
float lastHitTimer=0;
|
||||
std::shared_ptr<DamageNumber>damageNumberPtr;
|
||||
int phase=0;
|
||||
bool diesNormally=true; //If set to false, the monster death is handled in a special way. Set it to true when it's time to die.
|
||||
float iframeTimeUponHit=0;
|
||||
protected:
|
||||
public:
|
||||
Monster()=delete;
|
||||
@ -128,6 +131,7 @@ public:
|
||||
static void InitializeStrategies();
|
||||
bool HasIframes();
|
||||
float GetZ();
|
||||
std::string GetStrategy();
|
||||
private:
|
||||
struct STRATEGY{
|
||||
static int _GetInt(Monster&m,std::string param,int strategyNumber,int index=0);
|
||||
|
@ -332,7 +332,7 @@ void Player::Update(float fElapsedTime){
|
||||
SetX(newX);
|
||||
SetY(newY);
|
||||
}
|
||||
if(attack_cooldown_timer==0&&game->GetMouse(0).bHeld){
|
||||
if(CanAct()&&attack_cooldown_timer==0&&game->GetMouse(0).bHeld){
|
||||
AutoAttack();
|
||||
}
|
||||
|
||||
@ -341,19 +341,21 @@ void Player::Update(float fElapsedTime){
|
||||
//If pressed is set to false, uses held instead.
|
||||
auto CheckAndPerformAbility=[&](Ability&ability,HWButton key){
|
||||
if(ability.name!="???"){
|
||||
if(ability.cooldown==0&&GetMana()>=ability.manaCost){
|
||||
if(key.bHeld||key.bReleased&&&ability==castPrepAbility&&GetState()==State::PREP_CAST){
|
||||
if(AllowedToCast(ability)&&ability.action(this,{})){
|
||||
ability.cooldown=ability.COOLDOWN_TIME;
|
||||
mana-=ability.manaCost;
|
||||
}else
|
||||
if(ability.precastInfo.precastTargetingRequired&&GetState()==State::NORMAL){
|
||||
PrepareCast(ability);
|
||||
if(CanAct()){
|
||||
if(ability.cooldown==0&&GetMana()>=ability.manaCost){
|
||||
if(key.bHeld||key.bReleased&&&ability==castPrepAbility&&GetState()==State::PREP_CAST){
|
||||
if(AllowedToCast(ability)&&ability.action(this,{})){
|
||||
ability.cooldown=ability.COOLDOWN_TIME;
|
||||
mana-=ability.manaCost;
|
||||
}else
|
||||
if(ability.precastInfo.precastTargetingRequired&&GetState()==State::NORMAL){
|
||||
PrepareCast(ability);
|
||||
}
|
||||
}
|
||||
} else
|
||||
if(ability.cooldown==0&&GetMana()<ability.manaCost&&key.bPressed){
|
||||
notEnoughManaDisplay={ability.name,1};
|
||||
}
|
||||
} else
|
||||
if(ability.cooldown==0&&GetMana()<ability.manaCost&&key.bPressed){
|
||||
notEnoughManaDisplay={ability.name,1};
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -480,6 +482,10 @@ bool Player::CanMove(){
|
||||
return state!=State::CASTING&&state!=State::ANIMATION_LOCK;
|
||||
}
|
||||
|
||||
bool Player::CanAct(){
|
||||
return state!=State::CASTING&&state!=State::ANIMATION_LOCK;
|
||||
}
|
||||
|
||||
bool Player::HasIframes(){
|
||||
return iframe_time>0;
|
||||
}
|
||||
|
@ -129,6 +129,7 @@ public:
|
||||
//The range is the search range in tiles.
|
||||
bool CanPathfindTo(vf2d pos,vf2d targetPos,float range=8);
|
||||
bool CanMove();
|
||||
bool CanAct();
|
||||
|
||||
void AddBuff(BuffType type,float duration,float intensity);
|
||||
std::vector<Buff>GetBuffs(BuffType buff);
|
||||
|
@ -6,23 +6,23 @@ INCLUDE_DATA
|
||||
|
||||
int Monster::STRATEGY::_GetInt(Monster&m,std::string param,int strategyNumber,int index){
|
||||
if(DATA["Monsters"][std::to_string(m.id)].HasProperty(param)){
|
||||
return DATA["Monsters"][std::to_string(m.id)][param].GetInt(index);
|
||||
return DATA["Monsters"][std::to_string(m.id)].GetProperty(param).GetInt(index);
|
||||
} else {
|
||||
return DATA["MonsterStrategy"][std::to_string(strategyNumber)][param].GetInt(index);
|
||||
return DATA["MonsterStrategy"][std::to_string(strategyNumber)].GetProperty(param).GetInt(index);
|
||||
}
|
||||
}
|
||||
float Monster::STRATEGY::_GetFloat(Monster&m,std::string param,int strategyNumber,int index){
|
||||
if(DATA["Monsters"][std::to_string(m.id)].HasProperty(param)){
|
||||
return DATA["Monsters"][std::to_string(m.id)][param].GetReal(index);
|
||||
return DATA["Monsters"][std::to_string(m.id)].GetProperty(param).GetReal(index);
|
||||
} else {
|
||||
return DATA["MonsterStrategy"][std::to_string(strategyNumber)][param].GetReal(index);
|
||||
return DATA["MonsterStrategy"][std::to_string(strategyNumber)].GetProperty(param).GetReal(index);
|
||||
}
|
||||
}
|
||||
std::string Monster::STRATEGY::_GetString(Monster&m,std::string param,int strategyNumber,int index){
|
||||
if(DATA["Monsters"][std::to_string(m.id)].HasProperty(param)){
|
||||
return DATA["Monsters"][std::to_string(m.id)][param].GetString(index);
|
||||
return DATA["Monsters"][std::to_string(m.id)].GetProperty(param).GetString(index);
|
||||
} else {
|
||||
return DATA["MonsterStrategy"][std::to_string(strategyNumber)][param].GetString(index);
|
||||
return DATA["MonsterStrategy"][std::to_string(strategyNumber)].GetProperty(param).GetString(index);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,5 +8,32 @@ INCLUDE_game
|
||||
INCLUDE_BULLET_LIST
|
||||
|
||||
void Monster::STRATEGY::SLIMEKING(Monster&m,float fElapsedTime,int strategyNumber){
|
||||
|
||||
switch(m.phase){
|
||||
case 0:{
|
||||
m.size=ConfigInt("Phase1.Size")/100;
|
||||
m.diesNormally=false;
|
||||
m.iframeTimeUponHit=ConfigFloat("Phase5.IframeTimePerHit");
|
||||
m.phase=1;
|
||||
}break;
|
||||
case 1:{
|
||||
if(m.hp<=m.maxhp*ConfigFloat("Phase2.Change")/100){
|
||||
m.phase=2;
|
||||
}
|
||||
}break;
|
||||
case 2:{
|
||||
if(m.hp<=m.maxhp*ConfigFloat("Phase3.Change")/100){
|
||||
m.phase=3;
|
||||
}
|
||||
}break;
|
||||
case 3:{
|
||||
if(m.hp<=m.maxhp*ConfigFloat("Phase4.Change")/100){
|
||||
m.phase=4;
|
||||
}
|
||||
}break;
|
||||
case 4:{
|
||||
if(m.hp<=0){
|
||||
m.phase=5;
|
||||
}
|
||||
}break;
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 2
|
||||
#define VERSION_PATCH 0
|
||||
#define VERSION_BUILD 1041
|
||||
#define VERSION_BUILD 1057
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
@ -36,7 +36,7 @@ bool Warrior::AutoAttack(){
|
||||
for(Monster&m:MONSTER_LIST){
|
||||
if(m.IsAlive()
|
||||
&&m.OnUpperLevel()==OnUpperLevel()
|
||||
&&geom2d::overlaps(geom2d::circle<float>(GetPos()-vf2d{GetSizeMult()*12,GetSizeMult()*12},attack_range*GetSizeMult()*12),geom2d::circle<float>(m.GetPos()-vf2d{m.GetSizeMult()*12,m.GetSizeMult()*12},m.GetSizeMult()*12))
|
||||
&&geom2d::overlaps(geom2d::circle<float>(GetPos(),attack_range*GetSizeMult()*12),geom2d::circle<float>(m.GetPos(),m.GetSizeMult()*12))
|
||||
&&geom2d::line<float>(game->GetWorldMousePos(),m.GetPos()).length()<closest_dist){
|
||||
closest_dist=geom2d::line<float>(game->GetWorldMousePos(),m.GetPos()).length();
|
||||
closest=&m;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -5,7 +5,7 @@ Levels
|
||||
WORLD_MAP = World_Map.tmx
|
||||
|
||||
CAMPAIGN_1_1 = 1_1.tmx
|
||||
BOSS_1 = Boss_1.tmx
|
||||
BOSS_1 = Boss_1_v2.tmx
|
||||
|
||||
CAMPAIGN_1_2 = 1_2.tmx
|
||||
}
|
@ -87,6 +87,7 @@ namespace olc::utils
|
||||
{
|
||||
if (nItem >= m_vContent.size()){
|
||||
std::cout<<"WARNING! Accesing out-of-bounds list item "<<nItem<<" of "<<lastAccessedProperty<<"!"<<std::endl;
|
||||
throw;
|
||||
return "";
|
||||
}
|
||||
else {
|
||||
|
Loading…
x
Reference in New Issue
Block a user