Added NPC structures and new NPCs to the hub map.

pull/35/head
sigonasr2 12 months ago
parent 51e838de24
commit ebf7fcf395
  1. 6
      Adventures in Lestoria.sln
  2. 4
      Adventures in Lestoria/Adventures in Lestoria.tiled-project
  3. 82
      Adventures in Lestoria/Adventures in Lestoria.vcxproj
  4. 6
      Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters
  5. 12
      Adventures in Lestoria/AdventuresInLestoria.cpp
  6. 12
      Adventures in Lestoria/Monster.cpp
  7. 6
      Adventures in Lestoria/Monster.h
  8. 155
      Adventures in Lestoria/MonsterData.cpp
  9. 45
      Adventures in Lestoria/NPC.cpp
  10. 1
      Adventures in Lestoria/RUN_STRATEGY.cpp
  11. 62
      Adventures in Lestoria/TMXParser.h
  12. 2
      Adventures in Lestoria/TODO.txt
  13. 2
      Adventures in Lestoria/Version.h
  14. 10
      Adventures in Lestoria/assets/Campaigns/World_Map.tmx
  15. 3
      Adventures in Lestoria/assets/config/MonsterStrategies.txt
  16. 69
      Adventures in Lestoria/assets/config/NPCs.txt
  17. 3
      Adventures in Lestoria/assets/config/configuration.txt
  18. 0
      Adventures in Lestoria/assets/npcs/Traveling Merchant.png

@ -15,8 +15,6 @@ Global
Emscripten|x86 = Emscripten|x86
Release Desktop|x64 = Release Desktop|x64
Release Desktop|x86 = Release Desktop|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8E3067AF-CFE7-4B11-BC6B-B867C32753D7}.Debug|x64.ActiveCfg = Debug|x64
@ -35,10 +33,6 @@ Global
{8E3067AF-CFE7-4B11-BC6B-B867C32753D7}.Release Desktop|x64.Build.0 = Release Desktop|x64
{8E3067AF-CFE7-4B11-BC6B-B867C32753D7}.Release Desktop|x86.ActiveCfg = Release Desktop|Win32
{8E3067AF-CFE7-4B11-BC6B-B867C32753D7}.Release Desktop|x86.Build.0 = Release Desktop|Win32
{8E3067AF-CFE7-4B11-BC6B-B867C32753D7}.Release|x64.ActiveCfg = Release|x64
{8E3067AF-CFE7-4B11-BC6B-B867C32753D7}.Release|x64.Build.0 = Release|x64
{8E3067AF-CFE7-4B11-BC6B-B867C32753D7}.Release|x86.ActiveCfg = Release|Win32
{8E3067AF-CFE7-4B11-BC6B-B867C32753D7}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

@ -216,7 +216,7 @@
"STORY_1_2",
"STORY_1_3",
"BOSS_1",
"BLACKSMITH",
"HUB",
"CAMPAIGN_1_B1",
"BOSS_1_B"
],
@ -507,7 +507,7 @@
"DUNGEON",
"BOSS",
"STORY",
"SHOP"
"HUB"
],
"valuesAsFlags": false
},

@ -29,18 +29,10 @@
<Configuration>Release Desktop</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
@ -57,13 +49,6 @@
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Desktop|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
@ -77,13 +62,6 @@
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Desktop|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
@ -111,18 +89,12 @@
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release Desktop|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release Desktop|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
@ -160,29 +132,6 @@
<Command>powershell.exe -ExecutionPolicy Bypass -NoProfile -NonInteractive -File update_version.ps1 "./version.h"</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalOptions>/MP8 %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>C:\Users\sigon\source\repos\AdventuresInLestoria\Adventures in Lestoria\discord-files;C:\Users\sigon\Documents\include;</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>freetype.lib;$(CoreLibraryDependencies);%(AdditionalDependencies);discord_game_sdk.dll.lib</AdditionalDependencies>
</Link>
<PreBuildEvent>
<Command>powershell.exe -ExecutionPolicy Bypass -NoProfile -NonInteractive -File update_version.ps1 "./version.h"</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Desktop|Win32'">
<ClCompile>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
@ -231,32 +180,6 @@
</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalOptions>/MP8 %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>C:\Users\sigon\source\repos\AdventuresInLestoria\Adventures in Lestoria\discord-files;C:\Users\sigon\Documents\include;</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>freetype.lib;$(CoreLibraryDependencies);%(AdditionalDependencies);discord_game_sdk.dll.lib</AdditionalDependencies>
</Link>
<PreBuildEvent>
<Command>powershell.exe -ExecutionPolicy Bypass -NoProfile -NonInteractive -File update_version.ps1 "./version.h"</Command>
</PreBuildEvent>
<PostBuildEvent>
<Command>powershell.exe -ExecutionPolicy Bypass -NoProfile -NonInteractive -File emscripten_build.ps1</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Desktop|x64'">
<ClCompile>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
@ -701,6 +624,10 @@
</SubType>
</ClCompile>
<ClCompile Include="Meteor.cpp" />
<ClCompile Include="NPC.cpp">
<SubType>
</SubType>
</ClCompile>
<ClCompile Include="OverworldMapLevelWindow.cpp" />
<ClCompile Include="OverworldMenuWindow.cpp">
<SubType>
@ -812,6 +739,7 @@
<Text Include="assets\config\levels.txt" />
<Text Include="assets\config\Monsters.txt" />
<Text Include="assets\config\MonsterStrategies.txt" />
<Text Include="assets\config\NPCs.txt" />
<Text Include="assets\config\Player.txt" />
<Text Include="assets\config\shops\Chapter 1 Merchants.txt" />
<Text Include="assets\config\shops\Chapter 2 Merchants.txt" />

@ -770,6 +770,9 @@
<ClCompile Include="State_GameHub.cpp">
<Filter>Source Files\Game States</Filter>
</ClCompile>
<ClCompile Include="NPC.cpp">
<Filter>Source Files\Monster Strategies</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="cpp.hint" />
@ -918,6 +921,9 @@
<Text Include="characters.txt">
<Filter>Documentation</Filter>
</Text>
<Text Include="assets\config\NPCs.txt">
<Filter>Configurations</Filter>
</Text>
</ItemGroup>
<ItemGroup>
<Image Include="assets\heart.ico">

@ -143,6 +143,9 @@ AiL::AiL()
std::string MONSTERS_CONFIG = CONFIG_PATH + "monsters_config"_S;
utils::datafile::Read(DATA,MONSTERS_CONFIG);
std::string NPC_CONFIG = CONFIG_PATH + "npc_config"_S;
utils::datafile::Read(DATA,NPC_CONFIG);
std::string MONSTERSTRATEGIES_CONFIG = CONFIG_PATH + "monsterstrategies_config"_S;
utils::datafile::Read(DATA,MONSTERSTRATEGIES_CONFIG);
@ -233,6 +236,7 @@ bool AiL::OnUserCreate(){
//Animations
sig::Animation::InitializeAnimations();
MonsterData::InitializeMonsterData();
MonsterData::InitializeNPCData();
sig::Animation::SetupPlayerAnimations();
view=TileTransformedView{GetScreenSize(),{1,1}};
@ -1982,11 +1986,19 @@ void AiL::LoadLevel(MapName map){
}
#pragma endregion
for(NPCData data:game->MAP_DATA[game->GetCurrentLevel()].npcs){
MONSTER_LIST.push_back(Monster{data.spawnPos,MONSTER_DATA[data.name]});
MONSTER_LIST.back().iframe_timer=INFINITE;
}
player->GetAbility1().cooldown=0.f;
player->GetAbility2().cooldown=0.f;
player->GetAbility3().cooldown=0.f;
player->GetAbility4().cooldown=0.f;
player->GetRightClickAbility().cooldown=0.f;
player->useItem1.cooldown=0.f;
player->useItem2.cooldown=0.f;
player->useItem3.cooldown=0.f;
player->upperLevel=false; //Assume player starts on lower level.
player->ForceSetPos(MAP_DATA[map].MapData.playerSpawnLocation); //Normal set pos does one axis and then the other, so this will make sure that we actually end up at the right spot and ignore collision rules.

@ -126,6 +126,18 @@ void Monster::PerformShootAnimation(){
void Monster::PerformIdleAnimation(){
animation.ChangeState(internal_animState,MONSTER_DATA[name].GetIdleAnimation());
}
void Monster::PerformNPCDownAnimation(){
animation.ChangeState(internal_animState,MONSTER_DATA[name].GetIdleAnimation());
}
void Monster::PerformNPCUpAnimation(){
animation.ChangeState(internal_animState,MONSTER_DATA[name].GetJumpAnimation());
}
void Monster::PerformNPCLeftAnimation(){
animation.ChangeState(internal_animState,MONSTER_DATA[name].GetShootAnimation());
}
void Monster::PerformNPCRightAnimation(){
animation.ChangeState(internal_animState,MONSTER_DATA[name].GetDeathAnimation());
}
void Monster::PerformOtherAnimation(const uint8_t otherInd){
animation.ChangeState(internal_animState,MONSTER_DATA[name].GetAnimations()[4+otherInd]);
}

@ -111,6 +111,7 @@ struct MonsterData{
const std::vector<MonsterDropData>&GetDropData();
std::string GetDisplayName();
static void InitializeMonsterData();
static void InitializeNPCData();
static std::map<std::string,Renderable*>imgs;
};
@ -154,6 +155,10 @@ public:
void PerformJumpAnimation();
void PerformShootAnimation();
void PerformIdleAnimation();
void PerformNPCDownAnimation();
void PerformNPCUpAnimation();
void PerformNPCLeftAnimation();
void PerformNPCRightAnimation();
void PerformOtherAnimation(const uint8_t otherInd);
bool OnUpperLevel();
void Moved();
@ -267,6 +272,7 @@ private:
static void WOLF(Monster&m,float fElapsedTime,std::string strategy);
static void BEAR(Monster&m,float fElapsedTime,std::string strategy);
static void URSULE(Monster&m,float fElapsedTime,std::string strategy);
static void NPC(Monster&m,float fElapsedTime,std::string strategy);
};
};

@ -206,6 +206,161 @@ void MonsterData::InitializeMonsterData(){
MONSTER_DATA[MonsterName]=monster;
}
}
void MonsterData::InitializeNPCData(){
for(auto&[key,size]:DATA["NPCs"].GetKeys()){
std::string NPCName=key;
if(MONSTER_DATA.count(key)){
ERR("WARNING! A monster with the name "<<key<<" already exists in the database! Duplicates are not allowed.")
}
std::vector<std::string>animations{
NPCName+"_IDLE",
NPCName+"_JUMP",
NPCName+"_SPIT",
NPCName+"_DIE",
};
MonsterData::imgs[NPCName]=NEW Renderable();
const rcode imgLoadResult=MonsterData::imgs[NPCName]->Load("assets/npcs/"+NPCName+".png");
if(imgLoadResult!=OK)ERR(std::format("WARNING! Image loading for NPC {} failed with result {}",NPCName,int(imgLoadResult)));
EventName hurtSound="";
EventName deathSound="";
EventName walkSound="";
int health=100;
int attack=0;
int xp=0;
float moveSpd=100.f;
float size=100.f;
int collisionDmg=0;
if(DATA["NPCs"][NPCName].HasProperty("Health"))health=DATA["NPCs"][NPCName]["Health"].GetInt();
if(DATA["NPCs"][NPCName].HasProperty("Attack"))attack=DATA["NPCs"][NPCName]["Attack"].GetInt();
if(DATA["NPCs"][NPCName].HasProperty("XP"))xp=DATA["NPCs"][NPCName]["XP"].GetInt();
if(DATA["NPCs"][NPCName].HasProperty("MoveSpd"))moveSpd=DATA["NPCs"][NPCName]["MoveSpd"].GetReal();
if(DATA["NPCs"][NPCName].HasProperty("Size"))moveSpd=DATA["NPCs"][NPCName]["Size"].GetReal();
if(DATA["NPCs"][NPCName].HasProperty("CollisionDmg"))collisionDmg=DATA["NPCs"][NPCName]["CollisionDmg"].GetInt();
if(DATA["NPCs"][NPCName].HasProperty("Hurt Sound")){
hurtSound=DATA["NPCs"][NPCName]["Hurt Sound"].GetString();
}
if(DATA["NPCs"][NPCName].HasProperty("Death Sound")){
deathSound=DATA["NPCs"][NPCName]["Death Sound"].GetString();
}
if(DATA["NPCs"][NPCName].HasProperty("Walk Sound")){
walkSound=DATA["NPCs"][NPCName]["Walk Sound"].GetString();
}
auto CreateHorizontalAnimationSequence=[&](Renderable&img,int frameCount,vf2d size,std::string state,int row,AnimationData data={}){
Animate2D::FrameSequence anim(data.frameDuration,data.style);
for(int i=0;i<frameCount;i++){
anim.AddFrame({&img,{{int(i*size.x),int(row*size.y)},size}});
}
ANIMATION_DATA[state]=anim;
};
for(int i=0;i<animations.size();i++){
std::string animationConfigName="";
std::string imgName="";
switch(i){
case 0:{
animationConfigName="Down";
imgName="_IDLE";
}break;
case 1:{
animationConfigName="Up";
imgName="_JUMP";
}break;
case 2:{
animationConfigName="Left";
imgName="_SPIT";
}break;
case 3:{
animationConfigName="Right";
imgName="_DIE";
}break;
}
Animate2D::Style style=Animate2D::Style::Repeat;
if(DATA["NPCs"][NPCName][animationConfigName+"Animation"].GetString(2)=="Repeat"){
style=Animate2D::Style::Repeat;
}else
if(DATA["NPCs"][NPCName][animationConfigName+"Animation"].GetString(2)=="OneShot"){
style=Animate2D::Style::OneShot;
}else
if(DATA["NPCs"][NPCName][animationConfigName+"Animation"].GetString(2)=="PingPong"){
style=Animate2D::Style::PingPong;
}else
if(DATA["NPCs"][NPCName][animationConfigName+"Animation"].GetString(2)=="Reverse"){
style=Animate2D::Style::Reverse;
}else{
ERR(std::format("WARNING! Invalid Animation Style specified: {}",int(style)));
}
int frameCount=DATA["NPCs"][NPCName][animationConfigName+"Animation"].GetInt(0);
vf2d frameSize=vf2d{float(DATA["NPCs"][NPCName]["SheetFrameSize"].GetInt(0)),float(DATA["NPCs"][NPCName]["SheetFrameSize"].GetInt(1))};
CreateHorizontalAnimationSequence(*MonsterData::imgs[NPCName],frameCount,frameSize,NPCName+imgName,i,AnimationData{float(DATA["NPCs"][NPCName][animationConfigName+"Animation"].GetReal(1)),style});
}
//Add additional custom animations defined in the config.
int animationCounter=0;
int row=4;
while(DATA["NPCs"][NPCName].HasProperty("ANIMATION["+std::to_string(animationCounter)+"]")){
animations.push_back(NPCName+"ANIMATION["+std::to_string(animationCounter)+"]");
#pragma region Parse Animation Data
Animate2D::Style style;
if(DATA["NPCs"][NPCName]["ANIMATION["+std::to_string(animationCounter)+"]"].GetString(2)=="Repeat"){
style=Animate2D::Style::Repeat;
}else
if(DATA["NPCs"][NPCName]["ANIMATION["+std::to_string(animationCounter)+"]"].GetString(2)=="OneShot"){
style=Animate2D::Style::OneShot;
}else
if(DATA["NPCs"][NPCName]["ANIMATION["+std::to_string(animationCounter)+"]"].GetString(2)=="PingPong"){
style=Animate2D::Style::PingPong;
}else
if(DATA["NPCs"][NPCName]["ANIMATION["+std::to_string(animationCounter)+"]"].GetString(2)=="Reverse"){
style=Animate2D::Style::Reverse;
}else{
ERR(std::format("WARNING! Invalid Animation Style specified: {}",int(style)));
}
int frameCount=DATA["NPCs"][NPCName]["ANIMATION["+std::to_string(animationCounter)+"]"].GetInt(0);
vf2d frameSize=vf2d{float(DATA["NPCs"][NPCName]["SheetFrameSize"].GetInt(0)),float(DATA["NPCs"][NPCName]["SheetFrameSize"].GetInt(1))};
CreateHorizontalAnimationSequence(*MonsterData::imgs[NPCName],frameCount,frameSize,NPCName+"ANIMATION["+std::to_string(animationCounter)+"]",row,AnimationData{float(DATA["NPCs"][NPCName]["ANIMATION["+std::to_string(animationCounter)+"]"].GetReal(1)),style});
#pragma endregion
row++;
animationCounter++;
}
std::vector<MonsterDropData>drops;
//Add drop items to monster data from the config.
int dropDataCounter=0;
while(DATA["NPCs"][NPCName].HasProperty("DROP["+std::to_string(dropDataCounter)+"]")){
datafile drop=DATA["NPCs"][NPCName]["DROP["+std::to_string(dropDataCounter)+"]"];
if(!ITEM_DATA.count(drop.GetString(0))){
ERR("Could not add drop "<<drop.GetString(0)<<" to "<<NPCName<<"'s drop table! Item does not exist!");
}
drops.push_back(MonsterDropData{drop.GetString(0),float(drop.GetReal(1)),drop.GetInt(2),drop.GetInt(3)});
dropDataCounter++;
}
const std::string&strategyName=DATA["NPCs"][NPCName]["Strategy"].GetString();
if(!STRATEGY_DATA.count(strategyName)){
ERR("WARNING! Strategy for "<<NPCName<<" does not exist in strategy database!");
}
MonsterData monster(NPCName,health,attack,xp,animations,drops,moveSpd,size/100,strategyName,collisionDmg);
monster.hurtSound=hurtSound;
monster.deathSound=deathSound;
monster.walkSound=walkSound;
MONSTER_DATA[NPCName]=monster;
}
}
int MonsterData::GetHealth(){
return hp;
}

@ -0,0 +1,45 @@
#pragma region License
/*
License (OLC-3)
~~~~~~~~~~~~~~~
Copyright 2024 Joshua Sigona <sigonasr2@gmail.com>
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions or derivations of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions or derivative works in binary form must reproduce the above
copyright notice. This list of conditions and the following disclaimer must be
reproduced in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may
be used to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
Portions of this software are copyright © 2023 The FreeType
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
All rights reserved.
*/
#pragma endregion
#include "Monster.h"
using A=Attribute;
void Monster::STRATEGY::NPC(Monster&m,float fElapsedTime,std::string strategy){
}

@ -52,6 +52,7 @@ void Monster::InitializeStrategies(){
STRATEGY_DATA.insert("Wolf",Monster::STRATEGY::WOLF);
STRATEGY_DATA.insert("Bear",Monster::STRATEGY::BEAR);
STRATEGY_DATA.insert("Ursule",Monster::STRATEGY::URSULE);
STRATEGY_DATA.insert("NPC",Monster::STRATEGY::NPC);
STRATEGY_DATA.SetInitialized();
}

@ -94,6 +94,16 @@ struct ZoneData{
bool isUpper=false;
};
struct NPCData{
std::string function="";
std::string name="";
std::string sprite="";
std::string spawnFlag="";
uint32_t roamingRange=0;
vf2d spawnPos;
NPCData(XMLTag npcTag);
};
struct Map{
friend class AiL;
friend class TMXParser;
@ -105,6 +115,7 @@ private:
std::vector<LayerTag> LayerData;
std::vector<EnvironmentalAudio>environmentalAudioData;
std::vector<ItemMapData>stageLoot;
std::vector<NPCData>npcs;
std::string mapType="";
std::string bgmSongName="";
BackdropName backdrop="";
@ -153,7 +164,9 @@ class TMXParser{
EnvironmentalAudio*prevAudioData=nullptr;
void ParseTag(std::string tag);
int monsterPropertyTagCount=-1;
bool inNPCTag=false;
XMLTag monsterTag;
XMLTag npcTag;
XMLTag spawnerLinkTag;
StagePlate*currentStagePlate;
std::vector<XMLTag>accumulatedMonsterTags;
@ -283,6 +296,37 @@ class TMXParser{
const std::string_view Map::GetMapDisplayName()const{
return name;
}
NPCData::NPCData(XMLTag npcTag){
const std::array<std::string,7>tags={"Function","NPC Name","Roaming Range","Spawn Flag","Spritesheet","x","y"};
for(int i=0;i<tags.size();i++){
if(npcTag.data.contains(tags[i])){
switch(i){
case 0:{ //Function
function=npcTag.GetString(tags[i]);
}break;
case 1:{ //NPC Name
name=npcTag.GetString(tags[i]);
}break;
case 2:{ //Roaming Range
roamingRange=npcTag.GetInteger(tags[i]);
}break;
case 3:{ //Spawn Flag
spawnFlag=npcTag.GetString(tags[i]);
}break;
case 4:{ //Spritesheet
sprite=npcTag.GetString(tags[i]);
}break;
case 5:{ //X
spawnPos.x=npcTag.GetFloat(tags[i]);
}break;
case 6:{ //Y
spawnPos.y=npcTag.GetFloat(tags[i]);
}break;
}
}
}
}
std::ostream& operator <<(std::ostream& os, std::vector<XMLTag>& rhs) {
for(XMLTag&tag:rhs){
os <<
@ -360,6 +404,10 @@ class TMXParser{
if (newTag.tag=="object"&&newTag.data["type"]!="StagePlate"){
currentStagePlate=nullptr;
}
if (newTag.tag=="object"&&newTag.data["type"]!="NPC"&&inNPCTag){
inNPCTag=false;
parsedMapInfo.npcs.push_back(NPCData{npcTag});
}
if (newTag.tag=="map"){
if(stoi(newTag.data["infinite"])==1){
@ -419,10 +467,18 @@ class TMXParser{
if (newTag.tag=="object"&&newTag.data["type"]=="PlayerSpawnLocation") {
parsedMapInfo.MapData.playerSpawnLocation={newTag.GetInteger("x")-newTag.GetInteger("width")/2,newTag.GetInteger("y")-newTag.GetInteger("height")/2};
} else
if (newTag.tag=="object"&&newTag.data["type"]=="NPC") {
if(inNPCTag)parsedMapInfo.npcs.push_back(NPCData{npcTag});
npcTag=newTag;
inNPCTag=true;
} else
if (newTag.tag=="object"&&newTag.data["type"]=="Monster") {
monsterTag=newTag;
monsterPropertyTagCount=0;
} else
} else
if (newTag.tag=="property"&&inNPCTag) {
npcTag.data[newTag.data["name"]]=newTag.data["value"];
}
if (newTag.tag=="property"&&monsterPropertyTagCount==0) {
if(newTag.data["value"]=="None")ERR(std::format("WARNING! Invalid monster type provided: {} in map {}",newTag.data["value"],fileName));
monsterTag.data["value"]=newTag.data["value"];
@ -515,6 +571,10 @@ class TMXParser{
}
}
if(inNPCTag){
parsedMapInfo.npcs.push_back(NPCData{npcTag});
}
if(infiniteMap){
#if _DEBUG
if(_DEBUG_MAP_LOAD_INFO)std::cout<<"Infinite map detected. Parsing stopped early."<<std::endl;

@ -26,7 +26,7 @@ Settings Menu
- If you leave a stage, the stage complete window still shows up, showing only the loot you obtained that session.
- No equip sounds for weapons?
- Large numbers when dealing normal damage?
- When setting loadout items while loading the game it should highlight the correct item in the consumables inventory as well.
January 31st

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 0
#define VERSION_MINOR 3
#define VERSION_PATCH 0
#define VERSION_BUILD 6517
#define VERSION_BUILD 6529
#define stringify(a) stringify_(a)
#define stringify_(a) #a

@ -2,7 +2,7 @@
<map version="1.10" tiledversion="1.10.1" class="Map" orientation="orthogonal" renderorder="left-down" width="250" height="177" tilewidth="4" tileheight="4" infinite="0" nextlayerid="5" nextobjectid="19">
<properties>
<property name="Background Music" propertytype="BGM" value="overworld"/>
<property name="Level Type" propertytype="LevelType" value="World Map"/>
<property name="Level Type" propertytype="LevelType" value="Hub"/>
<property name="Optimize" type="bool" value="true"/>
</properties>
<tileset firstgid="1" source="../maps/Minifantasy_TinyOverworldAllTiles.tsx"/>
@ -601,11 +601,11 @@
<property name="Unlock Condition" propertytype="Level" value="CAMPAIGN_1_2"/>
</properties>
</object>
<object id="8" name="Blacksmith I" type="StagePlate" x="416" y="416" width="20" height="24">
<object id="8" name="Base" type="StagePlate" x="416" y="416" width="20" height="24">
<properties>
<property name="Map" propertytype="Level" value="BLACKSMITH"/>
<property name="Type" propertytype="StageType" value="SHOP"/>
<property name="Unlock Condition" propertytype="Level" value="STORY_1_2"/>
<property name="Map" propertytype="Level" value="HUB"/>
<property name="Type" propertytype="StageType" value="HUB"/>
<property name="Unlock Condition" propertytype="Level" value="STORY_1_1"/>
</properties>
</object>
<object id="9" name="Stage IV" type="StagePlate" x="172" y="580" width="44" height="16">

@ -489,4 +489,7 @@ MonsterStrategy
End Wisp Fadeout Time = 0.4s
}
}
NPC
{
}
}

@ -0,0 +1,69 @@
NPCs
{
Greg
{
Strategy = NPC
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
DownAnimation = 1, 0.1, OneShot
UpAnimation = 1, 0.1, OneShot
LeftAnimation = 1, 0.1, OneShot
RightAnimation = 1, 0.1, OneShot
Hurt Sound = Monster Hurt
Death Sound = Slime Dead
Walk Sound = Slime Walk
#Additional custom animations go down below. Start with ANIMATION[0] Order is:
# File name, Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# NOTE: ANIMATION[0] will always be row 5 of an animation sheet, all numbers that follow are each below each other.
#ANIMATION[0] = 6, 0.1, Repeat
}
Sherman
{
Strategy = NPC
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
DownAnimation = 1, 0.1, OneShot
UpAnimation = 1, 0.1, OneShot
LeftAnimation = 1, 0.1, OneShot
RightAnimation = 1, 0.1, OneShot
Hurt Sound = Monster Hurt
Death Sound = Slime Dead
Walk Sound = Slime Walk
#Additional custom animations go down below. Start with ANIMATION[0] Order is:
# File name, Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# NOTE: ANIMATION[0] will always be row 5 of an animation sheet, all numbers that follow are each below each other.
#ANIMATION[0] = 6, 0.1, Repeat
}
Traveling Merchant
{
Strategy = NPC
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
DownAnimation = 1, 0.1, OneShot
UpAnimation = 1, 0.1, OneShot
LeftAnimation = 1, 0.1, OneShot
RightAnimation = 1, 0.1, OneShot
Hurt Sound = Monster Hurt
Death Sound = Slime Dead
Walk Sound = Slime Walk
#Additional custom animations go down below. Start with ANIMATION[0] Order is:
# File name, Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# NOTE: ANIMATION[0] will always be row 5 of an animation sheet, all numbers that follow are each below each other.
#ANIMATION[0] = 6, 0.1, Repeat
}
}

@ -23,6 +23,9 @@ player_config = Player.txt
# Monster Properties Loading Config
monsters_config = Monsters.txt
# NPC Loading Config
npc_config = NPCs.txt
# Monster Strategy Config
monsterstrategies_config = MonsterStrategies.txt

Loading…
Cancel
Save