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.

pull/57/head
sigonasr2 9 months ago
parent 64ea11b4af
commit 21b8a9c3cb
  1. 39
      Adventures in Lestoria/Adventures in Lestoria.tiled-project
  2. 26
      Adventures in Lestoria/AdventuresInLestoria.cpp
  3. 5
      Adventures in Lestoria/DEFINES.h
  4. 15
      Adventures in Lestoria/Monster.cpp
  5. 4
      Adventures in Lestoria/MonsterData.cpp
  6. 2
      Adventures in Lestoria/Player.cpp
  7. 8
      Adventures in Lestoria/Stone_Elemental.cpp
  8. 24
      Adventures in Lestoria/TMXParser.h
  9. 2
      Adventures in Lestoria/Version.h
  10. 45
      Adventures in Lestoria/assets/Campaigns/Boss_2_B.tmx
  11. 5
      Adventures in Lestoria/assets/maps/Monster_Presets.tmx
  12. 2
      Adventures in Lestoria/assets/maps/Monsters/Hawk_NOXP.tx
  13. 5
      Adventures in Lestoria/assets/maps/Monsters/Major Hawk.tx
  14. 5
      Adventures in Lestoria/assets/maps/Monsters/Zephy, King of Birds.tx
  15. BIN
      Adventures in Lestoria/assets/maps/monsters-tileset.png
  16. BIN
      x64/Release/Adventures in Lestoria.exe

@ -526,6 +526,45 @@
],
"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",
"drawFill": true,

@ -94,9 +94,10 @@ bool _DEBUG_MAP_LOAD_INFO = false;
vi2d WINDOW_SIZE={24*15,24*10};
safemap<std::string,Animate2D::FrameSequence>ANIMATION_DATA;
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::unique_ptr<Bullet>>BULLET_LIST;
std::optional<std::queue<MonsterSpawnerID>>SPAWNER_CONTROLLER;
safemap<std::string,Renderable>GFX;
utils::datafile DATA;
AiL*game;
@ -2390,6 +2391,7 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
#pragma endregion
SPAWNER_LIST.clear();
SPAWNER_CONTROLLER={};
foregroundTileGroups.clear();
upperForegroundTileGroups.clear();
MONSTER_LIST.clear();
@ -2452,6 +2454,17 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
#pragma region Monster Spawn Data Setup (Loading phase 2)
LoadingScreen::AddPhase([&](){
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){
SpawnerTag&spawnData=MAP_DATA[GetCurrentLevel()].SpawnerData[key];
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");
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;
});
#pragma endregion
@ -3493,8 +3512,9 @@ void AiL::InitializeDefaultKeybinds(){
}
void AiL::SetBossNameDisplay(std::string name,float time){
const bool HasNotBeenDisplayedYet=bossName=="";
bossName=name;
bossDisplayTimer=time;
if(HasNotBeenDisplayedYet)bossDisplayTimer=time; //Only display once.
}
bool AiL::InBossEncounter(){

@ -41,9 +41,12 @@ All rights reserved.
using BackdropName=std::string;
using MonsterSpawnerID=int;
#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_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_game extern AiL*game;
#define INCLUDE_MONSTER_DATA extern std::map<std::string,MonsterData>MONSTER_DATA;

@ -60,6 +60,8 @@ INCLUDE_game
INCLUDE_BULLET_LIST
INCLUDE_DATA
INCLUDE_GFX
INCLUDE_SPAWNER_LIST
INCLUDE_SPAWNER_CONTROLLER
safemap<std::string,std::function<void(Monster&,float,std::string)>>STRATEGY_DATA;
std::unordered_map<std::string,Renderable*>MonsterData::imgs;
@ -332,7 +334,7 @@ bool Monster::Update(float fElapsedTime){
if(!HasIframes()){
for(std::unique_ptr<Monster>&m:MONSTER_LIST){
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);
geom2d::line line(pos,m->GetPos());
float dist = line.length();
@ -810,7 +812,15 @@ void Monster::OnDeath(){
if(isBoss){
game->ReduceBossEncounterMobCount();
if(game->BossEncounterMobCount()==0){
const bool exitRingShouldNotSpawn=SPAWNER_CONTROLLER.has_value()&&!SPAWNER_CONTROLLER.value().empty();
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;
@ -822,6 +832,7 @@ void Monster::OnDeath(){
game->AddZone("EndZone",exitRing); //Create a 144x144 ring around the dead boss.
}
}
}
Unlock::IncreaseKillCount();
@ -1043,7 +1054,7 @@ const std::optional<float>Monster::GetTotalLifetime()const{
return MONSTER_DATA.at(GetName()).GetLifetime();
}
const float Monster::GetCollisionRadius()const{
return MONSTER_DATA.at(GetName()).GetCollisionRadius();
return MONSTER_DATA.at(GetName()).GetCollisionRadius()*GetSizeMult();
}
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("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(hasFourWaySpriteSheet)monster.SetUsesFourWaySprites();
@ -436,5 +436,5 @@ const std::optional<float>MonsterData::GetLifetime()const{
return lifetime;
}
const float MonsterData::GetCollisionRadius()const{
return collisionRadius*GetSizeMult();
return collisionRadius;
}

@ -867,7 +867,7 @@ void Player::Moved(){
castPrepAbility->waitForRelease=true;
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(GameState::STATE==GameState::states[States::GAME_RUN]){
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.F(A::CASTING_TIMER)=ConfigFloat("Stone Pillar Cast Time");
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"),"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"),"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()*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;
case 1:{
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){
game->SpawnMonster(m.V(A::LOCKON_POS),MONSTER_DATA.at("Stone Pillar"),m.OnUpperLevel());
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()};
const vf2d targetWalkPos=stonePillarCastLine.rpoint(stonePillarCastLine.length()+48.f);
m.target=targetWalkPos;

@ -46,6 +46,7 @@ All rights reserved.
#include "ItemMapData.h"
#include "Class.h"
#include "MonsterData.h"
#include <queue>
INCLUDE_MONSTER_DATA
@ -133,7 +134,8 @@ private:
std::unordered_map<Class,float>devCompletionTrialTime;
BackdropName backdrop="";
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;
const std::map<std::string,std::vector<::ZoneData>>&GetZones()const;
public:
@ -146,6 +148,8 @@ public:
const float GetDevCompletionTime(Class cl)const;
const MapName&GetMapName()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 FormatSpawnerData(std::ostream& os, std::map<int,SpawnerTag>tiles);
friend std::ostream& operator << (std::ostream& os, Map& rhs);
@ -184,6 +188,7 @@ class TMXParser{
XMLTag npcTag;
XMLTag spawnerLinkTag;
StagePlate*currentStagePlate=nullptr;
std::optional<XMLTag>spawnControllerTag;
std::vector<XMLTag>accumulatedMonsterTags;
std::map<int,StagePlate>stagePlates;
bool infiniteMap=false;
@ -312,6 +317,15 @@ class TMXParser{
const std::string_view Map::GetMapDisplayName()const{
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(XMLTag npcTag){
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;
parsedMapInfo.npcs.push_back(NPCData{npcTag});
}
if(newTag.tag=="object"&&newTag.data["type"]!="SpawnController"&&spawnControllerTag.has_value())spawnControllerTag={};
if (newTag.tag=="map"){
if(stoi(newTag.data["infinite"])==1){
@ -454,6 +469,9 @@ class TMXParser{
parsedMapInfo.LayerData.push_back(l);
currentLayerTag=&parsedMapInfo.LayerData.back();
}else
if (newTag.tag=="object"&&newTag.data["type"]=="SpawnController"){
spawnControllerTag=newTag;
}else
if (newTag.tag=="object"&&newTag.data["type"]=="SpawnGroup"){
if(newTag.GetInteger("id")!=0){
parsedMapInfo.SpawnerData[newTag.GetInteger("id")]={newTag};
@ -518,6 +536,10 @@ class TMXParser{
monsterTag=newTag;
monsterPropertyTagCount=0;
}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) {
npcTag.data[newTag.data["name"]]=newTag.data["value"];
}else

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 1
#define VERSION_MINOR 2
#define VERSION_PATCH 0
#define VERSION_BUILD 9362
#define VERSION_BUILD 9378
#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.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>
<property name="Backdrop" propertytype="Backdrop" value="mountain_night"/>
<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
</data>
</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">
<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">
<properties>
<property name="Boss Title Display" value="Zephy, King of Birds"/>
@ -614,7 +653,7 @@
<property name="spawner" type="object" value="3"/>
</properties>
</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>
<property name="spawner" type="object" value="3"/>
</properties>

@ -1,5 +1,5 @@
<?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"/>
<layer id="1" name="Tile Layer 1" width="30" height="20">
<data encoding="csv"/>
@ -23,5 +23,8 @@
<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="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>
</map>

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<template>
<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>

@ -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

Loading…
Cancel
Save