Update No XP/Drop Hawk labels in Tiled Editor. Added spawn controllers, setup multi-tiered spawns. Fixed collision radius bugs. Added Chapter 2 Bonus Boss and Major Hawks Tiled Templates. Fix Stone Elemental Casting circle radius. Release Build 9378.
This commit is contained in:
parent
64ea11b4af
commit
21b8a9c3cb
@ -526,6 +526,45 @@
|
|||||||
],
|
],
|
||||||
"valuesAsFlags": false
|
"valuesAsFlags": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"color": "#ffa0a0a4",
|
||||||
|
"drawFill": true,
|
||||||
|
"id": 42,
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"name": "Spawn1",
|
||||||
|
"type": "object",
|
||||||
|
"value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Spawn2",
|
||||||
|
"type": "object",
|
||||||
|
"value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Spawn3",
|
||||||
|
"type": "object",
|
||||||
|
"value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Spawn4",
|
||||||
|
"type": "object",
|
||||||
|
"value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Spawn5",
|
||||||
|
"type": "object",
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "SpawnController",
|
||||||
|
"type": "class",
|
||||||
|
"useAs": [
|
||||||
|
"property",
|
||||||
|
"object",
|
||||||
|
"project"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"color": "#ffe67300",
|
"color": "#ffe67300",
|
||||||
"drawFill": true,
|
"drawFill": true,
|
||||||
|
@ -94,9 +94,10 @@ bool _DEBUG_MAP_LOAD_INFO = false;
|
|||||||
vi2d WINDOW_SIZE={24*15,24*10};
|
vi2d WINDOW_SIZE={24*15,24*10};
|
||||||
safemap<std::string,Animate2D::FrameSequence>ANIMATION_DATA;
|
safemap<std::string,Animate2D::FrameSequence>ANIMATION_DATA;
|
||||||
std::vector<std::unique_ptr<Monster>>MONSTER_LIST;
|
std::vector<std::unique_ptr<Monster>>MONSTER_LIST;
|
||||||
std::vector<MonsterSpawner>SPAWNER_LIST;
|
std::unordered_map<MonsterSpawnerID,MonsterSpawner>SPAWNER_LIST;
|
||||||
std::vector<std::shared_ptr<DamageNumber>>DAMAGENUMBER_LIST;
|
std::vector<std::shared_ptr<DamageNumber>>DAMAGENUMBER_LIST;
|
||||||
std::vector<std::unique_ptr<Bullet>>BULLET_LIST;
|
std::vector<std::unique_ptr<Bullet>>BULLET_LIST;
|
||||||
|
std::optional<std::queue<MonsterSpawnerID>>SPAWNER_CONTROLLER;
|
||||||
safemap<std::string,Renderable>GFX;
|
safemap<std::string,Renderable>GFX;
|
||||||
utils::datafile DATA;
|
utils::datafile DATA;
|
||||||
AiL*game;
|
AiL*game;
|
||||||
@ -2390,6 +2391,7 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
|
|||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
SPAWNER_LIST.clear();
|
SPAWNER_LIST.clear();
|
||||||
|
SPAWNER_CONTROLLER={};
|
||||||
foregroundTileGroups.clear();
|
foregroundTileGroups.clear();
|
||||||
upperForegroundTileGroups.clear();
|
upperForegroundTileGroups.clear();
|
||||||
MONSTER_LIST.clear();
|
MONSTER_LIST.clear();
|
||||||
@ -2452,6 +2454,17 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
|
|||||||
#pragma region Monster Spawn Data Setup (Loading phase 2)
|
#pragma region Monster Spawn Data Setup (Loading phase 2)
|
||||||
LoadingScreen::AddPhase([&](){
|
LoadingScreen::AddPhase([&](){
|
||||||
SetMosaicEffect(1U);
|
SetMosaicEffect(1U);
|
||||||
|
std::unordered_set<MonsterSpawnerID>IdsToDisable; //
|
||||||
|
if(MAP_DATA[GetCurrentLevel()].spawnControllerIDs.has_value()){
|
||||||
|
std::queue<MonsterSpawnerID>spawnController=MAP_DATA[GetCurrentLevel()].spawnControllerIDs.value();
|
||||||
|
while(!spawnController.empty()){
|
||||||
|
const int spawnerId=spawnController.front();
|
||||||
|
spawnController.pop();
|
||||||
|
auto result=IdsToDisable.insert(spawnerId);
|
||||||
|
if(!result.second)ERR(std::format("WARNING! Duplicate spawnerId {} detected when loading monster spawners. THIS SHOULD NOT BE HAPPENING!",spawnerId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(auto&[key,value]:MAP_DATA[GetCurrentLevel()].SpawnerData){
|
for(auto&[key,value]:MAP_DATA[GetCurrentLevel()].SpawnerData){
|
||||||
SpawnerTag&spawnData=MAP_DATA[GetCurrentLevel()].SpawnerData[key];
|
SpawnerTag&spawnData=MAP_DATA[GetCurrentLevel()].SpawnerData[key];
|
||||||
std::vector<std::pair<std::string,vf2d>>monster_list;
|
std::vector<std::pair<std::string,vf2d>>monster_list;
|
||||||
@ -2461,8 +2474,14 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
|
|||||||
std::string monsterName=monster.GetString("value");
|
std::string monsterName=monster.GetString("value");
|
||||||
monster_list.push_back({monsterName,{monster.GetInteger("x")-spawnData.ObjectData.GetFloat("x"),monster.GetInteger("y")-spawnData.ObjectData.GetFloat("y")}});
|
monster_list.push_back({monsterName,{monster.GetInteger("x")-spawnData.ObjectData.GetFloat("x"),monster.GetInteger("y")-spawnData.ObjectData.GetFloat("y")}});
|
||||||
}
|
}
|
||||||
SPAWNER_LIST.push_back(MonsterSpawner{{spawnData.ObjectData.GetFloat("x"),spawnData.ObjectData.GetFloat("y")},spawnerRadius*2,monster_list,spawnData.upperLevel,spawnData.bossNameDisplay});
|
|
||||||
|
const int spawnerId=spawnData.ObjectData.GetInteger("id");
|
||||||
|
|
||||||
|
if(SPAWNER_LIST.count(spawnerId))ERR(std::format("WARNING! Spawner ID {} for Map {} is somehow duplicated! THIS SHOULD NOT BE HAPPENING!",spawnData.ObjectData.GetInteger("id"),GetCurrentMapDisplayName()))
|
||||||
|
SPAWNER_LIST[spawnerId]=MonsterSpawner{{spawnData.ObjectData.GetFloat("x"),spawnData.ObjectData.GetFloat("y")},spawnerRadius*2,monster_list,spawnData.upperLevel,spawnData.bossNameDisplay};
|
||||||
|
if(IdsToDisable.count(spawnerId))SPAWNER_LIST.at(spawnerId).SetTriggered(true,false); //Force this spawner to be deactivated because it is in a spawn controller.
|
||||||
}
|
}
|
||||||
|
SPAWNER_CONTROLLER=MAP_DATA[GetCurrentLevel()].spawnControllerIDs;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
@ -3493,8 +3512,9 @@ void AiL::InitializeDefaultKeybinds(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AiL::SetBossNameDisplay(std::string name,float time){
|
void AiL::SetBossNameDisplay(std::string name,float time){
|
||||||
|
const bool HasNotBeenDisplayedYet=bossName=="";
|
||||||
bossName=name;
|
bossName=name;
|
||||||
bossDisplayTimer=time;
|
if(HasNotBeenDisplayedYet)bossDisplayTimer=time; //Only display once.
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AiL::InBossEncounter(){
|
bool AiL::InBossEncounter(){
|
||||||
|
@ -41,9 +41,12 @@ All rights reserved.
|
|||||||
|
|
||||||
using BackdropName=std::string;
|
using BackdropName=std::string;
|
||||||
|
|
||||||
|
using MonsterSpawnerID=int;
|
||||||
|
|
||||||
#define INCLUDE_ANIMATION_DATA extern safemap<std::string,Animate2D::FrameSequence>ANIMATION_DATA;
|
#define INCLUDE_ANIMATION_DATA extern safemap<std::string,Animate2D::FrameSequence>ANIMATION_DATA;
|
||||||
#define INCLUDE_MONSTER_LIST extern std::vector<std::unique_ptr<Monster>>MONSTER_LIST;
|
#define INCLUDE_MONSTER_LIST extern std::vector<std::unique_ptr<Monster>>MONSTER_LIST;
|
||||||
#define INCLUDE_SPAWNER_LIST extern std::vector<MonsterSpawner>SPAWNER_LIST;
|
#define INCLUDE_SPAWNER_LIST extern std::unordered_map<MonsterSpawnerID,MonsterSpawner>SPAWNER_LIST;
|
||||||
|
#define INCLUDE_SPAWNER_CONTROLLER extern std::optional<std::queue<MonsterSpawnerID>>SPAWNER_CONTROLLER;
|
||||||
#define INCLUDE_DAMAGENUMBER_LIST extern std::vector<std::shared_ptr<DamageNumber>>DAMAGENUMBER_LIST;
|
#define INCLUDE_DAMAGENUMBER_LIST extern std::vector<std::shared_ptr<DamageNumber>>DAMAGENUMBER_LIST;
|
||||||
#define INCLUDE_game extern AiL*game;
|
#define INCLUDE_game extern AiL*game;
|
||||||
#define INCLUDE_MONSTER_DATA extern std::map<std::string,MonsterData>MONSTER_DATA;
|
#define INCLUDE_MONSTER_DATA extern std::map<std::string,MonsterData>MONSTER_DATA;
|
||||||
|
@ -60,6 +60,8 @@ INCLUDE_game
|
|||||||
INCLUDE_BULLET_LIST
|
INCLUDE_BULLET_LIST
|
||||||
INCLUDE_DATA
|
INCLUDE_DATA
|
||||||
INCLUDE_GFX
|
INCLUDE_GFX
|
||||||
|
INCLUDE_SPAWNER_LIST
|
||||||
|
INCLUDE_SPAWNER_CONTROLLER
|
||||||
|
|
||||||
safemap<std::string,std::function<void(Monster&,float,std::string)>>STRATEGY_DATA;
|
safemap<std::string,std::function<void(Monster&,float,std::string)>>STRATEGY_DATA;
|
||||||
std::unordered_map<std::string,Renderable*>MonsterData::imgs;
|
std::unordered_map<std::string,Renderable*>MonsterData::imgs;
|
||||||
@ -332,7 +334,7 @@ bool Monster::Update(float fElapsedTime){
|
|||||||
if(!HasIframes()){
|
if(!HasIframes()){
|
||||||
for(std::unique_ptr<Monster>&m:MONSTER_LIST){
|
for(std::unique_ptr<Monster>&m:MONSTER_LIST){
|
||||||
if(&*m==this)continue;
|
if(&*m==this)continue;
|
||||||
if(!m->HasIframes()&&OnUpperLevel()==m->OnUpperLevel()&&abs(m->GetZ()-GetZ())<=1&&geom2d::overlaps(geom2d::circle(pos,GetCollisionRadius()),geom2d::circle(m->GetPos(),12*m->GetSizeMult()/2))){
|
if(!m->HasIframes()&&OnUpperLevel()==m->OnUpperLevel()&&abs(m->GetZ()-GetZ())<=1&&geom2d::overlaps(geom2d::circle(pos,GetCollisionRadius()),geom2d::circle(m->GetPos(),m->GetCollisionRadius()))){
|
||||||
m->Collision(*this);
|
m->Collision(*this);
|
||||||
geom2d::line line(pos,m->GetPos());
|
geom2d::line line(pos,m->GetPos());
|
||||||
float dist = line.length();
|
float dist = line.length();
|
||||||
@ -810,16 +812,25 @@ void Monster::OnDeath(){
|
|||||||
|
|
||||||
if(isBoss){
|
if(isBoss){
|
||||||
game->ReduceBossEncounterMobCount();
|
game->ReduceBossEncounterMobCount();
|
||||||
|
|
||||||
if(game->BossEncounterMobCount()==0){
|
if(game->BossEncounterMobCount()==0){
|
||||||
ZoneData exitRing{geom2d::rect<int>{vi2d{GetPos()-vf2d{"boss_spawn_ring_radius"_F,"boss_spawn_ring_radius"_F}},vi2d{"boss_spawn_ring_radius"_I*2,"boss_spawn_ring_radius"_I*2}},OnUpperLevel()};
|
const bool exitRingShouldNotSpawn=SPAWNER_CONTROLLER.has_value()&&!SPAWNER_CONTROLLER.value().empty();
|
||||||
|
|
||||||
const geom2d::rect<int>arenaBounds=game->GetZones().at("BossArena")[0].zone;
|
|
||||||
geom2d::rect<int>clampedArena{vi2d(arenaBounds.pos+"boss_spawn_ring_radius"_I),vi2d(arenaBounds.size-"boss_spawn_ring_radius"_I*2)};
|
|
||||||
|
|
||||||
exitRing.zone.pos.x=std::clamp(exitRing.zone.pos.x,clampedArena.pos.x-"boss_spawn_ring_radius"_I,clampedArena.pos.x-"boss_spawn_ring_radius"_I+clampedArena.size.x);
|
|
||||||
exitRing.zone.pos.y=std::clamp(exitRing.zone.pos.y,clampedArena.pos.y-"boss_spawn_ring_radius"_I,clampedArena.pos.y-"boss_spawn_ring_radius"_I+clampedArena.size.y);
|
|
||||||
|
|
||||||
game->AddZone("EndZone",exitRing); //Create a 144x144 ring around the dead boss.
|
if(exitRingShouldNotSpawn){ //See if we have a spawn controller and if we do, spawn the monsters from it instead of spawning the boss ring first.
|
||||||
|
const int nextSpawnerId=SPAWNER_CONTROLLER.value().front();
|
||||||
|
SPAWNER_CONTROLLER.value().pop();
|
||||||
|
SPAWNER_LIST[nextSpawnerId].SetTriggered(true);
|
||||||
|
}else{
|
||||||
|
ZoneData exitRing{geom2d::rect<int>{vi2d{GetPos()-vf2d{"boss_spawn_ring_radius"_F,"boss_spawn_ring_radius"_F}},vi2d{"boss_spawn_ring_radius"_I*2,"boss_spawn_ring_radius"_I*2}},OnUpperLevel()};
|
||||||
|
|
||||||
|
const geom2d::rect<int>arenaBounds=game->GetZones().at("BossArena")[0].zone;
|
||||||
|
geom2d::rect<int>clampedArena{vi2d(arenaBounds.pos+"boss_spawn_ring_radius"_I),vi2d(arenaBounds.size-"boss_spawn_ring_radius"_I*2)};
|
||||||
|
|
||||||
|
exitRing.zone.pos.x=std::clamp(exitRing.zone.pos.x,clampedArena.pos.x-"boss_spawn_ring_radius"_I,clampedArena.pos.x-"boss_spawn_ring_radius"_I+clampedArena.size.x);
|
||||||
|
exitRing.zone.pos.y=std::clamp(exitRing.zone.pos.y,clampedArena.pos.y-"boss_spawn_ring_radius"_I,clampedArena.pos.y-"boss_spawn_ring_radius"_I+clampedArena.size.y);
|
||||||
|
|
||||||
|
game->AddZone("EndZone",exitRing); //Create a 144x144 ring around the dead boss.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1043,7 +1054,7 @@ const std::optional<float>Monster::GetTotalLifetime()const{
|
|||||||
return MONSTER_DATA.at(GetName()).GetLifetime();
|
return MONSTER_DATA.at(GetName()).GetLifetime();
|
||||||
}
|
}
|
||||||
const float Monster::GetCollisionRadius()const{
|
const float Monster::GetCollisionRadius()const{
|
||||||
return MONSTER_DATA.at(GetName()).GetCollisionRadius();
|
return MONSTER_DATA.at(GetName()).GetCollisionRadius()*GetSizeMult();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Monster::MarkForDeletion(){
|
void Monster::MarkForDeletion(){
|
||||||
|
@ -185,7 +185,7 @@ void MonsterData::InitializeMonsterData(){
|
|||||||
if(DATA["Monsters"][MonsterName].HasProperty("Invulnerable"))monster.invulnerable=DATA["Monsters"][MonsterName]["Invulnerable"].GetBool();
|
if(DATA["Monsters"][MonsterName].HasProperty("Invulnerable"))monster.invulnerable=DATA["Monsters"][MonsterName]["Invulnerable"].GetBool();
|
||||||
if(DATA["Monsters"][MonsterName].HasProperty("Lifetime"))monster.lifetime=DATA["Monsters"][MonsterName]["Lifetime"].GetReal();
|
if(DATA["Monsters"][MonsterName].HasProperty("Lifetime"))monster.lifetime=DATA["Monsters"][MonsterName]["Lifetime"].GetReal();
|
||||||
|
|
||||||
monster.collisionRadius=12*monster.GetSizeMult()/2.f;
|
monster.collisionRadius=8;
|
||||||
if(DATA["Monsters"][MonsterName].HasProperty("Collision Radius"))monster.collisionRadius=DATA["Monsters"][MonsterName]["Collision Radius"].GetReal();
|
if(DATA["Monsters"][MonsterName].HasProperty("Collision Radius"))monster.collisionRadius=DATA["Monsters"][MonsterName]["Collision Radius"].GetReal();
|
||||||
|
|
||||||
if(hasFourWaySpriteSheet)monster.SetUsesFourWaySprites();
|
if(hasFourWaySpriteSheet)monster.SetUsesFourWaySprites();
|
||||||
@ -436,5 +436,5 @@ const std::optional<float>MonsterData::GetLifetime()const{
|
|||||||
return lifetime;
|
return lifetime;
|
||||||
}
|
}
|
||||||
const float MonsterData::GetCollisionRadius()const{
|
const float MonsterData::GetCollisionRadius()const{
|
||||||
return collisionRadius*GetSizeMult();
|
return collisionRadius;
|
||||||
}
|
}
|
@ -867,7 +867,7 @@ void Player::Moved(){
|
|||||||
castPrepAbility->waitForRelease=true;
|
castPrepAbility->waitForRelease=true;
|
||||||
CancelCast();
|
CancelCast();
|
||||||
}
|
}
|
||||||
for(MonsterSpawner&spawner:SPAWNER_LIST){
|
for(auto&[spawnerID,spawner]:SPAWNER_LIST){
|
||||||
if(!spawner.SpawnTriggered()&&spawner.DoesUpperLevelSpawning()==OnUpperLevel()&&geom2d::contains(geom2d::rect<float>{spawner.GetPos(),spawner.GetRange()},pos)){
|
if(!spawner.SpawnTriggered()&&spawner.DoesUpperLevelSpawning()==OnUpperLevel()&&geom2d::contains(geom2d::rect<float>{spawner.GetPos(),spawner.GetRange()},pos)){
|
||||||
if(GameState::STATE==GameState::states[States::GAME_RUN]){
|
if(GameState::STATE==GameState::states[States::GAME_RUN]){
|
||||||
if(!Tutorial::TaskIsComplete(TutorialTaskName::USE_ATTACK)){
|
if(!Tutorial::TaskIsComplete(TutorialTaskName::USE_ATTACK)){
|
||||||
|
@ -96,8 +96,8 @@ void Monster::STRATEGY::STONE_ELEMENTAL(Monster&m,float fElapsedTime,std::string
|
|||||||
m.phase=STONE_PILLAR_CAST;
|
m.phase=STONE_PILLAR_CAST;
|
||||||
m.F(A::CASTING_TIMER)=ConfigFloat("Stone Pillar Cast Time");
|
m.F(A::CASTING_TIMER)=ConfigFloat("Stone Pillar Cast Time");
|
||||||
m.V(A::LOCKON_POS)=game->GetPlayer()->GetPos();
|
m.V(A::LOCKON_POS)=game->GetPlayer()->GetPos();
|
||||||
game->AddEffect(std::make_unique<Effect>(m.V(A::LOCKON_POS),ConfigFloat("Stone Pillar Cast Time"),"range_indicator.png",m.OnUpperLevel(),vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Pillar").GetCollisionRadius()/12.f)*1.1f,0.3f,vf2d{},ConfigPixel("Stone Pillar Spell Circle Color"),util::random(2*PI),util::degToRad(ConfigFloat("Stone Pillar Spell Circle Rotation Spd"))),true);
|
game->AddEffect(std::make_unique<Effect>(m.V(A::LOCKON_POS),ConfigFloat("Stone Pillar Cast Time"),"range_indicator.png",m.OnUpperLevel(),vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Pillar").GetSizeMult()/12.f)*1.1f,0.3f,vf2d{},ConfigPixel("Stone Pillar Spell Circle Color"),util::random(2*PI),util::degToRad(ConfigFloat("Stone Pillar Spell Circle Rotation Spd"))),true);
|
||||||
game->AddEffect(std::make_unique<Effect>(m.V(A::LOCKON_POS),ConfigFloat("Stone Pillar Cast Time"),"spell_insignia.png",m.OnUpperLevel(),vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Pillar").GetCollisionRadius()/12.f)*0.75f,0.3f,vf2d{},ConfigPixel("Stone Pillar Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Stone Pillar Spell Insignia Rotation Spd"))),true);
|
game->AddEffect(std::make_unique<Effect>(m.V(A::LOCKON_POS),ConfigFloat("Stone Pillar Cast Time"),"spell_insignia.png",m.OnUpperLevel(),vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Pillar").GetSizeMult()/12.f)*0.75f,0.3f,vf2d{},ConfigPixel("Stone Pillar Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Stone Pillar Spell Insignia Rotation Spd"))),true);
|
||||||
}break;
|
}break;
|
||||||
case 1:{
|
case 1:{
|
||||||
m.PerformAnimation("ROCK TOSS CAST");
|
m.PerformAnimation("ROCK TOSS CAST");
|
||||||
@ -128,9 +128,9 @@ void Monster::STRATEGY::STONE_ELEMENTAL(Monster&m,float fElapsedTime,std::string
|
|||||||
if(m.F(A::CASTING_TIMER)<=0.f){
|
if(m.F(A::CASTING_TIMER)<=0.f){
|
||||||
game->SpawnMonster(m.V(A::LOCKON_POS),MONSTER_DATA.at("Stone Pillar"),m.OnUpperLevel());
|
game->SpawnMonster(m.V(A::LOCKON_POS),MONSTER_DATA.at("Stone Pillar"),m.OnUpperLevel());
|
||||||
ReturnToWaitingPhase();
|
ReturnToWaitingPhase();
|
||||||
game->Hurt(m.V(A::LOCKON_POS),MONSTER_DATA.at("Stone Pillar").GetCollisionRadius(),m.GetAttack(),m.OnUpperLevel(),0.f,HurtType::PLAYER);
|
game->Hurt(m.V(A::LOCKON_POS),MONSTER_DATA.at("Stone Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Pillar").GetSizeMult(),m.GetAttack(),m.OnUpperLevel(),0.f,HurtType::PLAYER);
|
||||||
}
|
}
|
||||||
if(geom2d::overlaps(geom2d::circle<float>{m.V(A::LOCKON_POS),MONSTER_DATA.at("Stone Pillar").GetCollisionRadius()},geom2d::circle<float>{m.GetPos(),m.GetCollisionRadius()})){
|
if(geom2d::overlaps(geom2d::circle<float>{m.V(A::LOCKON_POS),MONSTER_DATA.at("Stone Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Pillar").GetSizeMult()},geom2d::circle<float>{m.GetPos(),m.GetCollisionRadius()})){
|
||||||
geom2d::line<float>stonePillarCastLine{m.V(A::LOCKON_POS),m.GetPos()};
|
geom2d::line<float>stonePillarCastLine{m.V(A::LOCKON_POS),m.GetPos()};
|
||||||
const vf2d targetWalkPos=stonePillarCastLine.rpoint(stonePillarCastLine.length()+48.f);
|
const vf2d targetWalkPos=stonePillarCastLine.rpoint(stonePillarCastLine.length()+48.f);
|
||||||
m.target=targetWalkPos;
|
m.target=targetWalkPos;
|
||||||
|
@ -46,6 +46,7 @@ All rights reserved.
|
|||||||
#include "ItemMapData.h"
|
#include "ItemMapData.h"
|
||||||
#include "Class.h"
|
#include "Class.h"
|
||||||
#include "MonsterData.h"
|
#include "MonsterData.h"
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
INCLUDE_MONSTER_DATA
|
INCLUDE_MONSTER_DATA
|
||||||
|
|
||||||
@ -133,7 +134,8 @@ private:
|
|||||||
std::unordered_map<Class,float>devCompletionTrialTime;
|
std::unordered_map<Class,float>devCompletionTrialTime;
|
||||||
BackdropName backdrop="";
|
BackdropName backdrop="";
|
||||||
std::set<std::string>spawns;
|
std::set<std::string>spawns;
|
||||||
std::map<int,SpawnerTag> SpawnerData; //Spawn groups have IDs, mobs associate which spawner they are tied to via this ID.
|
std::map<int,SpawnerTag>SpawnerData; //Spawn groups have IDs, mobs associate which spawner they are tied to via this ID.
|
||||||
|
std::optional<std::queue<MonsterSpawnerID>>spawnControllerIDs;
|
||||||
std::map<std::string,std::vector<::ZoneData>> ZoneData;
|
std::map<std::string,std::vector<::ZoneData>> ZoneData;
|
||||||
const std::map<std::string,std::vector<::ZoneData>>&GetZones()const;
|
const std::map<std::string,std::vector<::ZoneData>>&GetZones()const;
|
||||||
public:
|
public:
|
||||||
@ -146,6 +148,8 @@ public:
|
|||||||
const float GetDevCompletionTime(Class cl)const;
|
const float GetDevCompletionTime(Class cl)const;
|
||||||
const MapName&GetMapName()const;
|
const MapName&GetMapName()const;
|
||||||
const std::string_view GetMapDisplayName()const;
|
const std::string_view GetMapDisplayName()const;
|
||||||
|
const bool HasMoreSpawns()const; //Returns whether or not there are more spawns for the spawn controller.
|
||||||
|
const int Spawn_pop(); //Grabs the next spawn controller ID and removes it from the stack.
|
||||||
std::string FormatLayerData(std::ostream& os, std::vector<LayerTag>tiles);
|
std::string FormatLayerData(std::ostream& os, std::vector<LayerTag>tiles);
|
||||||
std::string FormatSpawnerData(std::ostream& os, std::map<int,SpawnerTag>tiles);
|
std::string FormatSpawnerData(std::ostream& os, std::map<int,SpawnerTag>tiles);
|
||||||
friend std::ostream& operator << (std::ostream& os, Map& rhs);
|
friend std::ostream& operator << (std::ostream& os, Map& rhs);
|
||||||
@ -184,6 +188,7 @@ class TMXParser{
|
|||||||
XMLTag npcTag;
|
XMLTag npcTag;
|
||||||
XMLTag spawnerLinkTag;
|
XMLTag spawnerLinkTag;
|
||||||
StagePlate*currentStagePlate=nullptr;
|
StagePlate*currentStagePlate=nullptr;
|
||||||
|
std::optional<XMLTag>spawnControllerTag;
|
||||||
std::vector<XMLTag>accumulatedMonsterTags;
|
std::vector<XMLTag>accumulatedMonsterTags;
|
||||||
std::map<int,StagePlate>stagePlates;
|
std::map<int,StagePlate>stagePlates;
|
||||||
bool infiniteMap=false;
|
bool infiniteMap=false;
|
||||||
@ -312,6 +317,15 @@ class TMXParser{
|
|||||||
const std::string_view Map::GetMapDisplayName()const{
|
const std::string_view Map::GetMapDisplayName()const{
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
const bool Map::HasMoreSpawns()const{
|
||||||
|
return spawnControllerIDs.has_value()&&spawnControllerIDs.value().size()>0;
|
||||||
|
}
|
||||||
|
const int Map::Spawn_pop(){
|
||||||
|
if(!HasMoreSpawns())ERR("WARNING! Trying to pop from queue when there are no items! Make sure to use HasMoreSpawns() first!");
|
||||||
|
const int nextSpawnId=spawnControllerIDs.value().front();
|
||||||
|
spawnControllerIDs.value().pop();
|
||||||
|
return nextSpawnId;
|
||||||
|
}
|
||||||
NPCData::NPCData(){}
|
NPCData::NPCData(){}
|
||||||
NPCData::NPCData(XMLTag npcTag){
|
NPCData::NPCData(XMLTag npcTag){
|
||||||
const std::array<std::string,7>tags={"Function","NPC Name","Roaming Range","Unlock Condition","Spritesheet","x","y"};
|
const std::array<std::string,7>tags={"Function","NPC Name","Roaming Range","Unlock Condition","Spritesheet","x","y"};
|
||||||
@ -435,6 +449,7 @@ class TMXParser{
|
|||||||
inNPCTag=false;
|
inNPCTag=false;
|
||||||
parsedMapInfo.npcs.push_back(NPCData{npcTag});
|
parsedMapInfo.npcs.push_back(NPCData{npcTag});
|
||||||
}
|
}
|
||||||
|
if(newTag.tag=="object"&&newTag.data["type"]!="SpawnController"&&spawnControllerTag.has_value())spawnControllerTag={};
|
||||||
|
|
||||||
if (newTag.tag=="map"){
|
if (newTag.tag=="map"){
|
||||||
if(stoi(newTag.data["infinite"])==1){
|
if(stoi(newTag.data["infinite"])==1){
|
||||||
@ -454,6 +469,9 @@ class TMXParser{
|
|||||||
parsedMapInfo.LayerData.push_back(l);
|
parsedMapInfo.LayerData.push_back(l);
|
||||||
currentLayerTag=&parsedMapInfo.LayerData.back();
|
currentLayerTag=&parsedMapInfo.LayerData.back();
|
||||||
}else
|
}else
|
||||||
|
if (newTag.tag=="object"&&newTag.data["type"]=="SpawnController"){
|
||||||
|
spawnControllerTag=newTag;
|
||||||
|
}else
|
||||||
if (newTag.tag=="object"&&newTag.data["type"]=="SpawnGroup"){
|
if (newTag.tag=="object"&&newTag.data["type"]=="SpawnGroup"){
|
||||||
if(newTag.GetInteger("id")!=0){
|
if(newTag.GetInteger("id")!=0){
|
||||||
parsedMapInfo.SpawnerData[newTag.GetInteger("id")]={newTag};
|
parsedMapInfo.SpawnerData[newTag.GetInteger("id")]={newTag};
|
||||||
@ -518,6 +536,10 @@ class TMXParser{
|
|||||||
monsterTag=newTag;
|
monsterTag=newTag;
|
||||||
monsterPropertyTagCount=0;
|
monsterPropertyTagCount=0;
|
||||||
}else
|
}else
|
||||||
|
if(newTag.tag=="property"&&spawnControllerTag.has_value()) {
|
||||||
|
if(!parsedMapInfo.HasMoreSpawns())parsedMapInfo.spawnControllerIDs=std::queue<int>{};
|
||||||
|
parsedMapInfo.spawnControllerIDs.value().push(newTag.GetInteger("value"));
|
||||||
|
}else
|
||||||
if (newTag.tag=="property"&&inNPCTag) {
|
if (newTag.tag=="property"&&inNPCTag) {
|
||||||
npcTag.data[newTag.data["name"]]=newTag.data["value"];
|
npcTag.data[newTag.data["name"]]=newTag.data["value"];
|
||||||
}else
|
}else
|
||||||
|
@ -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 0
|
#define VERSION_PATCH 0
|
||||||
#define VERSION_BUILD 9362
|
#define VERSION_BUILD 9378
|
||||||
|
|
||||||
#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.2" class="Map" orientation="orthogonal" renderorder="right-down" width="160" height="144" tilewidth="24" tileheight="24" infinite="0" nextlayerid="6" nextobjectid="14">
|
<map version="1.10" tiledversion="1.10.2" class="Map" orientation="orthogonal" renderorder="right-down" width="160" height="144" tilewidth="24" tileheight="24" infinite="0" nextlayerid="9" nextobjectid="26">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="Backdrop" propertytype="Backdrop" value="mountain_night"/>
|
<property name="Backdrop" propertytype="Backdrop" value="mountain_night"/>
|
||||||
<property name="Background Music" propertytype="BGM" value="foresty_boss"/>
|
<property name="Background Music" propertytype="BGM" value="foresty_boss"/>
|
||||||
@ -601,8 +601,47 @@
|
|||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
</data>
|
</data>
|
||||||
</layer>
|
</layer>
|
||||||
|
<objectgroup id="8" name="Spawn Controller/Arena">
|
||||||
|
<object id="23" name="Spawn Controller" type="SpawnController" x="1326" y="1158" width="276" height="228">
|
||||||
|
<properties>
|
||||||
|
<property name="Spawn1" type="object" value="16"/>
|
||||||
|
<property name="Spawn2" type="object" value="19"/>
|
||||||
|
</properties>
|
||||||
|
</object>
|
||||||
|
<object id="25" name="Boss Arena" type="BossArena" x="1302" y="1122" width="1448" height="1206"/>
|
||||||
|
</objectgroup>
|
||||||
|
<objectgroup id="7" name="Spawn Zone 3" visible="0">
|
||||||
|
<object id="19" name="Boss Spawn Zone" type="SpawnGroup" x="1560" y="1314" width="964" height="882">
|
||||||
|
<properties>
|
||||||
|
<property name="Boss Title Display" value="Zephy, King of Birds"/>
|
||||||
|
</properties>
|
||||||
|
<ellipse/>
|
||||||
|
</object>
|
||||||
|
<object id="22" template="../maps/Monsters/Zephy, King of Birds.tx" x="1956" y="1572">
|
||||||
|
<properties>
|
||||||
|
<property name="spawner" type="object" value="19"/>
|
||||||
|
</properties>
|
||||||
|
</object>
|
||||||
|
</objectgroup>
|
||||||
|
<objectgroup id="6" name="Spawn Zone 2" visible="0">
|
||||||
|
<object id="16" name="Major Hawk Spawn Zone" type="SpawnGroup" x="1560" y="1314" width="964" height="882">
|
||||||
|
<properties>
|
||||||
|
<property name="Boss Title Display" value="Zephy, King of Birds"/>
|
||||||
|
</properties>
|
||||||
|
<ellipse/>
|
||||||
|
</object>
|
||||||
|
<object id="17" template="../maps/Monsters/Major Hawk.tx" x="1956" y="1608">
|
||||||
|
<properties>
|
||||||
|
<property name="spawner" type="object" value="16"/>
|
||||||
|
</properties>
|
||||||
|
</object>
|
||||||
|
<object id="18" template="../maps/Monsters/Major Hawk.tx" x="2082" y="1608">
|
||||||
|
<properties>
|
||||||
|
<property name="spawner" type="object" value="16"/>
|
||||||
|
</properties>
|
||||||
|
</object>
|
||||||
|
</objectgroup>
|
||||||
<objectgroup id="5" name="Spawn Zones">
|
<objectgroup id="5" name="Spawn Zones">
|
||||||
<object id="1" name="Boss Arena" type="BossArena" x="1302" y="1122" width="1448" height="1206"/>
|
|
||||||
<object id="3" name="Boss Fight Start Zone" type="SpawnGroup" x="1561" y="1320" width="964" height="498">
|
<object id="3" name="Boss Fight Start Zone" type="SpawnGroup" x="1561" y="1320" width="964" height="498">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="Boss Title Display" value="Zephy, King of Birds"/>
|
<property name="Boss Title Display" value="Zephy, King of Birds"/>
|
||||||
@ -614,7 +653,7 @@
|
|||||||
<property name="spawner" type="object" value="3"/>
|
<property name="spawner" type="object" value="3"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="6" template="../maps/Monsters/Hawk_NOXP.tx" x="2129" y="1386">
|
<object id="6" template="../maps/Monsters/Hawk_NOXP.tx" name="Hawk (No XP/Drop)" x="2129" y="1386">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="spawner" type="object" value="3"/>
|
<property name="spawner" type="object" value="3"/>
|
||||||
</properties>
|
</properties>
|
||||||
|
@ -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.2" orientation="orthogonal" renderorder="right-down" width="30" height="20" tilewidth="24" tileheight="24" infinite="1" nextlayerid="3" nextobjectid="26">
|
<map version="1.10" tiledversion="1.10.2" orientation="orthogonal" renderorder="right-down" width="30" height="20" tilewidth="24" tileheight="24" infinite="1" nextlayerid="3" nextobjectid="29">
|
||||||
<tileset firstgid="1" source="Monsters.tsx"/>
|
<tileset firstgid="1" source="Monsters.tsx"/>
|
||||||
<layer id="1" name="Tile Layer 1" width="30" height="20">
|
<layer id="1" name="Tile Layer 1" width="30" height="20">
|
||||||
<data encoding="csv"/>
|
<data encoding="csv"/>
|
||||||
@ -23,5 +23,8 @@
|
|||||||
<object id="18" template="Monsters/Stone Elemental.tx" type="Monster" x="180" y="156"/>
|
<object id="18" template="Monsters/Stone Elemental.tx" type="Monster" x="180" y="156"/>
|
||||||
<object id="22" template="Monsters/Goblin (Dagger).tx" type="Monster" x="26" y="226"/>
|
<object id="22" template="Monsters/Goblin (Dagger).tx" type="Monster" x="26" y="226"/>
|
||||||
<object id="25" template="Monsters/Goblin (Bombs).tx" type="Monster" x="142" y="222"/>
|
<object id="25" template="Monsters/Goblin (Bombs).tx" type="Monster" x="142" y="222"/>
|
||||||
|
<object id="26" template="Monsters/Hawk_NOXP.tx" type="Monster" x="143" y="92"/>
|
||||||
|
<object id="27" template="Monsters/Major Hawk.tx" type="Monster" x="180" y="96"/>
|
||||||
|
<object id="28" template="Monsters/Zephy, King of Birds.tx" type="Monster" x="-42" y="348"/>
|
||||||
</objectgroup>
|
</objectgroup>
|
||||||
</map>
|
</map>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<template>
|
<template>
|
||||||
<tileset firstgid="1" source="../Monsters.tsx"/>
|
<tileset firstgid="1" source="../Monsters.tsx"/>
|
||||||
<object name="Hawk_NOXP" type="Monster" gid="12" width="24" height="24"/>
|
<object name="Hawk (No XP/Drop)" type="Monster" gid="12" width="24" height="24"/>
|
||||||
</template>
|
</template>
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<template>
|
||||||
|
<tileset firstgid="1" source="../Monsters.tsx"/>
|
||||||
|
<object name="Major Hawk" type="Monster" gid="19" width="57.6" height="57.6"/>
|
||||||
|
</template>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<template>
|
||||||
|
<tileset firstgid="1" source="../Monsters.tsx"/>
|
||||||
|
<object name="Zephy, King of Birds" type="Monster" gid="20" width="192" height="192"/>
|
||||||
|
</template>
|
Binary file not shown.
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 12 KiB |
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user