diff --git a/C++ProjectTemplate b/C++ProjectTemplate index b26ef83..ff203e7 100755 Binary files a/C++ProjectTemplate and b/C++ProjectTemplate differ diff --git a/assets/maps/map0 b/assets/maps/map0 index d54c23c..4adc677 100644 --- a/assets/maps/map0 +++ b/assets/maps/map0 @@ -79,4 +79,7 @@ OBJECT288.000000;256.000000;2 OBJECT256.000000;256.000000;2 OBJECT224.000000;256.000000;2 OBJECT192.000000;256.000000;2 -OBJECT160.000000;256.000000;2 \ No newline at end of file +OBJECT160.000000;256.000000;2 +ENCOUNTER64;64;75;0 +ENCOUNTER64;256;30;1 +ENCOUNTER64;512;40;2 \ No newline at end of file diff --git a/cutscene.h b/cutscene.h index cdc1de3..cc3a244 100644 --- a/cutscene.h +++ b/cutscene.h @@ -29,7 +29,7 @@ enum class ActionType{ class CutsceneAction{ bool queued=false; //Set to true when added to action asynchronous queue. public: - virtual ActionType GetActionType(){}; + virtual ActionType GetActionType()=0; bool InQueue() { return queued; } @@ -310,9 +310,6 @@ class Cutscene{ //MAKE SURE TO DELETE ALL OBJECTS IN THE OBJECTS WORLD ARRAY BEFORE CALLING THIS! //THIS FUNCTION WILL DELETE THE POINTERS FOR YOU! void CleanupCutscene() { - for (int i=0;i -auto flagint(Enumeration const value) -> typename std::underlying_type::type +auto toint(Enumeration const value) -> typename std::underlying_type::type { return static_cast::type>(value); } \ No newline at end of file diff --git a/ideas b/ideas index 6cb705d..7598bd3 100644 --- a/ideas +++ b/ideas @@ -114,4 +114,28 @@ Create and Move Objects Pan the Camera Fade the game In/Out Start Dialog -Set Game Flags \ No newline at end of file +Set Game Flags + +Moveset Selection: +There will be a couple of AI sets that enemies can use: +-> Random - As the name implies, every move will be picked at random. +-> Ordered - Orderered just goes down the list in order. +-> Weighted - There is a 50% chance to do the top move, and everytime it's not picked, + there's a 50% chance for the next move to be picked, and this continues down and down. + If the end is reached, that move is picked. + Example scenario: There are 5 moves. + 50% Move 1 + 25% Move 2 + 12.5% Move 3 + 6.25% Move 4 + 6.25% Move 5 + +There will be a smart flag toggle. If smart is turned on, the AI will sometimes +try to use debuffs and healing moves when appropriate: Debuffs are attempted more +often in smart mode when players doesn't have said debuff yet and will try to avoid +the move if there's something better. Likewise, with smart mode if the enemy has a +healing move and is dying, it will attempt to use that. + +There is also a dumb flag. The dumb flag will make the enemy try to use PP draining moves +even if they don't have enough PP for that move. This will mean they will waste turns after +they run out of PP. \ No newline at end of file diff --git a/main.cpp b/main.cpp index b3f19ab..7dcf444 100644 --- a/main.cpp +++ b/main.cpp @@ -10,6 +10,7 @@ #include "flags.h" #include #include "cutscene.h" +#include "encounters.h" #define WIDTH 256 #define HEIGHT 224 @@ -25,6 +26,8 @@ ((AsyncClass*)CurrentCutscene->GetAction())->SetQueued(); \ CurrentCutscene->AdvanceAction(); \ +#define 액션 (CutsceneAction*)new + using namespace olc; namespace layer{ @@ -39,24 +42,6 @@ namespace layer{ }; } -class Map{ - public: - std::string filename; - std::string l2filename; - std::string l3filename; - std::string l4filename; - std::string l5filename; - Decal*tileset; - Map(std::string fname,std::string layer2_fname,std::string layer3_fname,std::string layer4_fname,std::string layer5_fname,Decal*tileset) { - this->filename=fname; - this->l2filename=layer2_fname; - this->l3filename=layer3_fname; - this->l4filename=layer4_fname; - this->l5filename=layer5_fname; - this->tileset=tileset; - } -}; - class Animation{ public: Decal*spr; @@ -107,6 +92,103 @@ class Object{ } }; +enum class Resistance{ + WET, + DRY, + COLD, + HEAT, +}; + +enum class Property{ + PETRIFY, + PARALYZE, + DIAMONDIZE, + CRYING, + SLOW, + MUSHROOMIZED, + CONFUSE, + POISON, + REGEN, + DEFENSE_UP, +}; + + +namespace Battle{ + class Move{ + public: + std::string name; + int composition[4]; + int baseDmg; //The base damage of the attack. + int randomDmg; //Additional random roll damage to add onto the base damage. + bool pctDamage; //Uses % damage for the base damage instead of flat damage. + std::vector> properties; //The int is used to determine the chance of something occurring. + Move(std::string name,int baseDmg,int randomDmg,int composition[4]={},bool pctDamage=false,std::vector> properties={}) + :name(name),randomDmg(randomDmg),baseDmg(baseDmg),pctDamage(pctDamage),properties(properties){ + for (int i=0;i<4;i++) { + this->composition[i]=composition[i]; + } + } + }; +} + +class Entity{ + public: + int HP=0; + int targetHP=0; + int maxHP=0; + int resistances[4]={0,0,0,0}; + int speed=0; + int baseAtk=0; + int damageReduction=0; //A percentage of how much damage to reduce. + bool smart=false; + bool dumb=false; + Object* obj; + std::vector moveSet; + Entity(Object*obj,int HP,int maxHP,int baseAtk,std::arrayresistances,int speed,std::vectormoveSet,int damageReduction=0,bool smart=false,bool dumb=false) { + this->obj=obj; + this->HP=this->targetHP=HP; + this->maxHP=maxHP; + for (int i=0;i<4;i++) { + this->resistances[i]=resistances[i]; + } + this->speed=speed; + this->moveSet=moveSet; + this->smart=smart; + this->dumb=dumb; + this->baseAtk=baseAtk; + this->damageReduction=damageReduction; + } +}; + +class Encounter{ + public: + vd2d pos; + int chance; //Chance of the encounter existing. + std::vectorobjs; + Encounter(vd2d pos,std::vectorobjs,int chance=25) + :pos(pos),objs(objs),chance(chance){} +}; + + +class Map{ + public: + std::string filename; + std::string l2filename; + std::string l3filename; + std::string l4filename; + std::string l5filename; + Decal*tileset; + std::vector encounters; + Map(std::string fname,std::string layer2_fname,std::string layer3_fname,std::string layer4_fname,std::string layer5_fname,Decal*tileset) { + this->filename=fname; + this->l2filename=layer2_fname; + this->l3filename=layer3_fname; + this->l4filename=layer4_fname; + this->l5filename=layer5_fname; + this->tileset=tileset; + } +}; + class SeasonI : public PixelGameEngine { public: @@ -194,21 +276,21 @@ public: LoadMap(MAP_ONETT); TestCutscene=new Cutscene({ - (CutsceneAction*)new Fade(), - (CutsceneAction*)new CreateObjects({ + 액션 Fade(), + 액션 CreateObjects({ new Object(PLAYER,"player",{64,64},ANIMATIONS["player.png"],{1,1},MAGENTA), new Object(PLAYER,"player",{136,136},ANIMATIONS["player.png"],{1,1},RED), new Object(PLAYER,"player",{96,96},ANIMATIONS["player.png"],{1,1},DARK_GREEN), }), - (CutsceneAction*)new Fade(true), - (CutsceneAction*)new SetFlagWhenCutsceneEnds(Flag::TEST_FLAG1), - (CutsceneAction*)new PanCamera({128,128},BOTH,1), - (CutsceneAction*)new MoveCutsceneObjectAsync(1,{80,64},5), - (CutsceneAction*)new PanCamera({64,0},BOTH), - (CutsceneAction*)new DialogBoxAsync(R"(Hello! + 액션 Fade(true), + 액션 SetFlagWhenCutsceneEnds(Flag::TEST_FLAG1), + 액션 PanCamera({128,128},BOTH,1), + 액션 MoveCutsceneObjectAsync(1,{80,64},5), + 액션 PanCamera({64,0},BOTH), + 액션 DialogBoxAsync(R"(Hello! This is a test message that lets us trigger straight from a cutscene! Cool!)"), - (CutsceneAction*)new ModifyObject(0,ANIMATIONS["player.png"],{5,5},MAGENTA), - (CutsceneAction*)new MoveCutsceneObject(1,{320,64},1),}); + 액션 ModifyObject(0,ANIMATIONS["player.png"],{5,5},MAGENTA), + 액션 MoveCutsceneObject(1,{320,64},1),}); /*DisplayMessageBox(R"(Hello World! This is a rather long message, but I hope it reaches you well in some form or capacity or another. Even though it @@ -312,6 +394,7 @@ goes on a very long time, I hope you can understand this is only for testing pur if (CUTSCENE_QUEUE.size()==0) { for (int i=0;itemp) { + delete OBJECTS[i]; OBJECTS.erase(OBJECTS.begin()+i--); } } @@ -798,7 +881,7 @@ goes on a very long time, I hope you can understand this is only for testing pur if (MAP_WIDTH==-1) { MAP_WIDTH=data.length()/2; } - if (data.find("OBJECT")!=std::string::npos) { + if (data.find("OBJECT")!=std::string::npos||data.find("ENCOUNTER")!=std::string::npos) { int marker=data.find_first_of(';'); int lastMarker=marker; std::stringstream split1(data.substr(6,marker-6)); @@ -816,21 +899,31 @@ goes on a very long time, I hope you can understand this is only for testing pur int id; split3>>id; - bool enabled=true; - if (OBJ_INFO[id]->disableFlag!=Flag::NONE) { - if (GetGameFlag(OBJ_INFO[id]->disableFlag)) { - enabled=false; + if (data.find("OBJECT")!=std::string::npos) { + bool enabled=true; + if (OBJ_INFO[id]->disableFlag!=Flag::NONE) { + if (GetGameFlag(OBJ_INFO[id]->disableFlag)) { + enabled=false; + } } - } - if (OBJ_INFO[id]->enableFlag!=Flag::NONE) { - if (!GetGameFlag(OBJ_INFO[id]->enableFlag)) { - enabled=false; + if (OBJ_INFO[id]->enableFlag!=Flag::NONE) { + if (!GetGameFlag(OBJ_INFO[id]->enableFlag)) { + enabled=false; + } } + if (enabled) { + AddObjectToWorld(CreateObject(id,{x,y})); + } + printf("Object %s Loaded.\n",OBJ_INFO[id]->name.c_str()); + } else + if (data.find("ENCOUNTER")!=std::string::npos) { + marker=data.find_first_of(';',marker+1); + std::stringstream split4(data.substr(lastMarker+1,marker-lastMarker-1)); + lastMarker=marker; + int pct=id; + split4>>id; + printf("Encounter %d (%d%) Loaded.\n",id,pct); } - if (enabled) { - AddObjectToWorld(CreateObject(id,{x,y})); - } - printf("Object %s Loaded.\n",OBJ_INFO[id]->name.c_str()); } else { std::vector tiles; printf("%s\n",data.c_str()); @@ -1428,11 +1521,27 @@ goes on a very long time, I hope you can understand this is only for testing pur } void SetGameFlag(Flag flag,bool val) { - GAME_FLAGS[flagint(flag)]=val; + GAME_FLAGS[toint(flag)]=val; } bool GetGameFlag(Flag flag) { - return GAME_FLAGS[flagint(flag)]; + return GAME_FLAGS[toint(flag)]; + } + + void LoadEncounter(Map*map,vd2d pos,int chance,int id) { + switch (id) { + case encounter::ENCOUNTER_1:{ + map->encounters.push_back( + new Encounter(pos, + std::vector{new Entity( + new Object( + NPC1_4,"Test Obj",{pos.x+20,pos.y+48},ANIMATIONS["player.png"] + ),70,70,14,std::array{0,0,0,0},0,std::vector{} + )} + ,chance) + ); + }break; + } } };