Added an overlay control class. Optimize and rearrange rendering order of bullets and effects such that all bullets now appear above monsters. Fix a bug involving some objects that are supposed to appear behind the player end up in front when they are aligned on the same tile row. Preparations for wind attack. Release Build 9482.

pull/57/head
sigonasr2 8 months ago
parent 3a9bd4afff
commit d3374062fe
  1. 8
      Adventures in Lestoria/Adventures in Lestoria.vcxproj
  2. 9
      Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters
  3. 527
      Adventures in Lestoria/AdventuresInLestoria.cpp
  4. 5
      Adventures in Lestoria/AdventuresInLestoria.h
  5. 9
      Adventures in Lestoria/Monster.cpp
  6. 3
      Adventures in Lestoria/Monster.h
  7. 68
      Adventures in Lestoria/Overlay.cpp
  8. 56
      Adventures in Lestoria/Overlay.h
  9. 2
      Adventures in Lestoria/RUN_STRATEGY.cpp
  10. 2
      Adventures in Lestoria/Version.h
  11. 41
      Adventures in Lestoria/Zephy.cpp
  12. 16
      Adventures in Lestoria/assets/config/MonsterStrategies.txt
  13. 1
      Adventures in Lestoria/assets/config/gfx/gfx.txt
  14. BIN
      Adventures in Lestoria/assets/gamepack.pak
  15. BIN
      Adventures in Lestoria/assets/wind1.png
  16. BIN
      Adventures in Lestoria/assets/wind2.png
  17. BIN
      Adventures in Lestoria/assets/wind_vignette.png
  18. BIN
      x64/Release/Adventures in Lestoria.exe

@ -425,6 +425,10 @@
</ClInclude>
<ClInclude Include="MonsterData.h" />
<ClInclude Include="olcPGEX_SplashScreen.h" />
<ClInclude Include="Overlay.h">
<SubType>
</SubType>
</ClInclude>
<ClInclude Include="PlayerMoneyLabel.h">
<SubType>
</SubType>
@ -815,6 +819,10 @@
<SubType>
</SubType>
</ClCompile>
<ClCompile Include="Overlay.cpp">
<SubType>
</SubType>
</ClCompile>
<ClCompile Include="OverworldMapLevelWindow.cpp" />
<ClCompile Include="OverworldMenuWindow.cpp">
<SubType>

@ -642,6 +642,9 @@
<ClInclude Include="Direction.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Overlay.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Player.cpp">
@ -1061,6 +1064,12 @@
<ClCompile Include="MajorHawk.cpp">
<Filter>Source Files\Monster Strategies</Filter>
</ClCompile>
<ClCompile Include="Tornado.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Overlay.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="cpp.hint" />

@ -156,8 +156,7 @@ InputGroup AiL::KEY_TOGGLE_MAP;
float AiL::SIZE_CHANGE_SPEED=1;
AiL::AiL()
{
AiL::AiL(){
debugLogger.open("debug.log");
utils::datafile::Read(DATA,"assets/config/configuration.txt");
std::filesystem::create_directories("save_file_path"_S);
@ -820,7 +819,6 @@ void AiL::PopulateRenderLists(){
monstersBeforeLower.clear();
monstersAfterLower.clear();
monstersBeforeUpper.clear();
monstersAfterUpper.clear();
bulletsLower.clear();
bulletsUpper.clear();
backgroundEffectsLower.clear();
@ -1267,63 +1265,55 @@ void AiL::RenderWorld(float fElapsedTime){
m.strategyDraw(this,m,MONSTER_DATA[m.GetName()].GetAIStrategy());
}
#pragma region Render Background Effects
{
auto it=backgroundEffectsLower.begin();
while(it!=backgroundEffectsLower.end()){
const Effect&e=**it;
e.Draw();
++it;
}
}
#pragma endregion
auto monstersBeforeLowerIt=monstersBeforeLower.begin();
auto monstersAfterLowerIt=monstersAfterLower.begin();
auto dropsBeforeLowerIt=dropsBeforeLower.begin();
auto dropsAfterLowerIt=dropsAfterLower.begin();
#pragma region Rendering before Tile Depth Rendering
if(tilesWithCollision.size()>0){
const float topTileY=(*tilesWithCollision.begin())->group->GetCollisionRange().middle().y;
#pragma region Depth Ordered Rendering
{
auto it=monstersBeforeLower.begin();
while(it!=monstersBeforeLower.end()){
Monster&m=**it;
if(m.pos.y<topTileY){
m.Draw();
it=monstersBeforeLower.erase(it);
if(it==monstersBeforeLower.end())break;
continue;
}
break;
while(monstersBeforeLowerIt!=monstersBeforeLower.end()){
Monster&m=**monstersBeforeLowerIt;
if(m.pos.y<topTileY){
m.Draw();
++monstersBeforeLowerIt;
continue;
}
break;
}
{
auto it=bulletsLower.begin();
while(it!=bulletsLower.end()){
const Bullet&b=**it;
if(b.pos.y<topTileY){
b.Draw();
it=bulletsLower.erase(it);
if(it==bulletsLower.end())break;
continue;
}
break;
while(dropsBeforeLowerIt!=dropsBeforeLower.end()){
const ItemDrop&drop=ItemDrop::drops[*dropsBeforeLowerIt];
if(drop.pos.y<topTileY){
drop.Draw();
++dropsBeforeLowerIt;
continue;
}
break;
}
{
auto it=backgroundEffectsLower.begin();
while(it!=backgroundEffectsLower.end()){
const Effect&e=**it;
if(e.pos.y<topTileY){
e.Draw();
it=backgroundEffectsLower.erase(it);
if(it==backgroundEffectsLower.end())break;
continue;
}
break;
if(!player->rendered&&!player->upperLevel&&player->GetPos().y<topTileY){
//If we are supposed to render the player, everything else before must be rendered at this point.
while(monstersBeforeLowerIt!=monstersBeforeLower.end()){
Monster&m=**monstersBeforeLowerIt;
m.Draw();
++monstersBeforeLowerIt;
}
}
{
auto it=dropsBeforeLower.begin();
while(it!=dropsBeforeLower.end()){
const ItemDrop&drop=ItemDrop::drops[*it];
if(drop.pos.y<topTileY){
drop.Draw();
it=dropsBeforeLower.erase(it);
if(it==dropsBeforeLower.end())break;
continue;
}
break;
while(dropsBeforeLowerIt!=dropsBeforeLower.end()){
const ItemDrop&drop=ItemDrop::drops[*dropsBeforeLowerIt];
drop.Draw();
++dropsBeforeLowerIt;
}
}
if(!player->rendered&&!player->upperLevel&&player->GetPos().y<topTileY){
player->rendered=true;
if(player->GetZ()>0){
vf2d shadowScale=vf2d{8*player->GetSizeMult()/3.f,1}/std::max(1.f,player->GetZ()/24);
@ -1331,44 +1321,23 @@ void AiL::RenderWorld(float fElapsedTime){
}
RenderPlayer(player->GetPos(),{1,1});
}
{
auto it=monstersAfterLower.begin();
while(it!=monstersAfterLower.end()){
Monster&m=**it;
if(m.pos.y<topTileY){
m.Draw();
it=monstersAfterLower.erase(it);
if(it==monstersAfterLower.end())break;
continue;
}
break;
}
}
{
auto it=dropsAfterLower.begin();
while(it!=dropsAfterLower.end()){
const ItemDrop&drop=ItemDrop::drops[*it];
if(drop.pos.y<topTileY){
drop.Draw();
it=dropsAfterLower.erase(it);
if(it==dropsAfterLower.end())break;
continue;
}
break;
while(monstersAfterLowerIt!=monstersAfterLower.end()){
Monster&m=**monstersAfterLowerIt;
if(m.pos.y<topTileY){
m.Draw();
++monstersAfterLowerIt;
continue;
}
break;
}
{
auto it=foregroundEffectsLower.begin();
while(it!=foregroundEffectsLower.end()){
const Effect&e=**it;
if(e.pos.y<topTileY){
e.Draw();
it=foregroundEffectsLower.erase(it);
if(it==foregroundEffectsLower.end())break;
continue;
}
break;
while(dropsAfterLowerIt!=dropsAfterLower.end()){
const ItemDrop&drop=ItemDrop::drops[*dropsAfterLowerIt];
if(drop.pos.y<topTileY){
drop.Draw();
++dropsAfterLowerIt;
continue;
}
break;
}
#pragma endregion
}
@ -1376,59 +1345,18 @@ void AiL::RenderWorld(float fElapsedTime){
#pragma region Foreground Rendering w/Depth
for(TileRenderData*tile:tilesWithCollision){
#pragma region Depth Ordered Rendering
{
auto it=monstersBeforeLower.begin();
while(it!=monstersBeforeLower.end()){
Monster&m=**it;
if(m.pos.y<tile->group->GetCollisionRange().middle().y){
m.Draw();
it=monstersBeforeLower.erase(it);
if(it==monstersBeforeLower.end())break;
continue;
}
break;
}
}
{
auto it=bulletsLower.begin();
while(it!=bulletsLower.end()){
const Bullet&b=**it;
if(b.pos.y<tile->group->GetCollisionRange().middle().y){
b.Draw();
it=bulletsLower.erase(it);
if(it==bulletsLower.end())break;
continue;
}
break;
}
}
{
auto it=backgroundEffectsLower.begin();
while(it!=backgroundEffectsLower.end()){
const Effect&e=**it;
if(e.pos.y<tile->group->GetCollisionRange().middle().y){
e.Draw();
it=backgroundEffectsLower.erase(it);
if(it==backgroundEffectsLower.end())break;
continue;
}
break;
if(!player->rendered&&!player->upperLevel&&player->GetPos().y<tile->group->GetCollisionRange().middle().y){
//If we are supposed to render the player, everything else before must be rendered at this point.
while(monstersBeforeLowerIt!=monstersBeforeLower.end()){
Monster&m=**monstersBeforeLowerIt;
m.Draw();
++monstersBeforeLowerIt;
}
}
{
auto it=dropsBeforeLower.begin();
while(it!=dropsBeforeLower.end()){
const ItemDrop&drop=ItemDrop::drops[*it];
if(drop.pos.y<tile->group->GetCollisionRange().middle().y){
drop.Draw();
it=dropsBeforeLower.erase(it);
if(it==dropsBeforeLower.end())break;
continue;
}
break;
while(dropsBeforeLowerIt!=dropsBeforeLower.end()){
const ItemDrop&drop=ItemDrop::drops[*dropsBeforeLowerIt];
drop.Draw();
++dropsBeforeLowerIt;
}
}
if(!player->rendered&&!player->upperLevel&&player->GetPos().y<tile->group->GetCollisionRange().middle().y){
player->rendered=true;
if(player->GetZ()>0){
vf2d shadowScale=vf2d{8*player->GetSizeMult()/3.f,1}/std::max(1.f,player->GetZ()/24);
@ -1436,44 +1364,23 @@ void AiL::RenderWorld(float fElapsedTime){
}
RenderPlayer(player->GetPos(),{1,1});
}
{
auto it=monstersAfterLower.begin();
while(it!=monstersAfterLower.end()){
Monster&m=**it;
if(m.pos.y<tile->group->GetCollisionRange().middle().y){
m.Draw();
it=monstersAfterLower.erase(it);
if(it==monstersAfterLower.end())break;
continue;
}
break;
}
}
{
auto it=dropsAfterLower.begin();
while(it!=dropsAfterLower.end()){
const ItemDrop&drop=ItemDrop::drops[*it];
if(drop.pos.y<tile->group->GetCollisionRange().middle().y){
drop.Draw();
it=dropsAfterLower.erase(it);
if(it==dropsAfterLower.end())break;
continue;
}
break;
while(monstersAfterLowerIt!=monstersAfterLower.end()){
Monster&m=**monstersAfterLowerIt;
if(m.pos.y<tile->group->GetCollisionRange().middle().y){
m.Draw();
++monstersAfterLowerIt;
continue;
}
break;
}
{
auto it=foregroundEffectsLower.begin();
while(it!=foregroundEffectsLower.end()){
const Effect&e=**it;
if(e.pos.y<tile->group->GetCollisionRange().middle().y){
e.Draw();
it=foregroundEffectsLower.erase(it);
if(it==foregroundEffectsLower.end())break;
continue;
}
break;
while(dropsAfterLowerIt!=dropsAfterLower.end()){
const ItemDrop&drop=ItemDrop::drops[*dropsAfterLowerIt];
if(drop.pos.y<tile->group->GetCollisionRange().middle().y){
drop.Draw();
++dropsAfterLowerIt;
continue;
}
break;
}
#pragma endregion
RenderTile(*tile,{255,255,255,uint8_t(255-tile->tileOpacity/TileGroup::FADE_TIME*TileGroup::FADE_AMT)});
@ -1503,9 +1410,6 @@ void AiL::RenderWorld(float fElapsedTime){
for(const Effect*const e:backgroundEffectsLower){
e->Draw();
}
for(const Bullet*const b:bulletsLower){
b->Draw();
}
for(const int dropInd:dropsBeforeLower){
ItemDrop::drops[dropInd].Draw();
}
@ -1524,6 +1428,9 @@ void AiL::RenderWorld(float fElapsedTime){
for(const int dropInd:dropsAfterLower){
ItemDrop::drops[dropInd].Draw();
}
for(const Bullet*const b:bulletsLower){
b->Draw();
}
for(const Effect*const e:foregroundEffectsLower){
e->Draw();
}
@ -1643,63 +1550,55 @@ void AiL::RenderWorld(float fElapsedTime){
m.strategyDraw(this,m,MONSTER_DATA[m.GetName()].GetAIStrategy());
}
#pragma region Render Background Effects
{
auto it=backgroundEffectsUpper.begin();
while(it!=backgroundEffectsUpper.end()){
const Effect&e=**it;
e.Draw();
++it;
}
}
#pragma endregion
auto monstersBeforeUpperIt=monstersBeforeUpper.begin();
auto monstersAfterUpperIt=monstersAfterUpper.begin();
auto dropsBeforeUpperIt=dropsBeforeUpper.begin();
auto dropsAfterUpperIt=dropsAfterUpper.begin();
#pragma region Rendering before Tile Depth Rendering
if(tilesWithCollision.size()>0){
const float topTileY=(*tilesWithCollision.begin())->group->GetCollisionRange().middle().y;
#pragma region Depth Ordered Rendering
{
auto it=monstersBeforeUpper.begin();
while(it!=monstersBeforeUpper.end()){
Monster&m=**it;
if(m.pos.y<topTileY){
m.Draw();
it=monstersBeforeUpper.erase(it);
if(it==monstersBeforeUpper.end())break;
continue;
}
break;
while(monstersBeforeUpperIt!=monstersBeforeUpper.end()){
Monster&m=**monstersBeforeUpperIt;
if(m.pos.y<topTileY){
m.Draw();
++monstersBeforeUpperIt;
continue;
}
break;
}
{
auto it=bulletsUpper.begin();
while(it!=bulletsUpper.end()){
const Bullet&b=**it;
if(b.pos.y<topTileY){
b.Draw();
it=bulletsUpper.erase(it);
if(it==bulletsUpper.end())break;
continue;
}
break;
while(dropsBeforeUpperIt!=dropsBeforeUpper.end()){
const ItemDrop&drop=ItemDrop::drops[*dropsBeforeUpperIt];
if(drop.pos.y<topTileY){
drop.Draw();
++dropsBeforeUpperIt;
continue;
}
break;
}
{
auto it=backgroundEffectsUpper.begin();
while(it!=backgroundEffectsUpper.end()){
const Effect&e=**it;
if(e.pos.y<topTileY){
e.Draw();
it=backgroundEffectsUpper.erase(it);
if(it==backgroundEffectsUpper.end())break;
continue;
}
break;
if(!player->rendered&&!player->upperLevel&&player->GetPos().y<topTileY){
//If we are supposed to render the player, everything else before must be rendered at this point.
while(monstersBeforeUpperIt!=monstersBeforeUpper.end()){
Monster&m=**monstersBeforeUpperIt;
m.Draw();
++monstersBeforeUpperIt;
}
}
{
auto it=dropsBeforeUpper.begin();
while(it!=dropsBeforeUpper.end()){
const ItemDrop&drop=ItemDrop::drops[*it];
if(drop.pos.y<topTileY){
drop.Draw();
it=dropsBeforeUpper.erase(it);
if(it==dropsBeforeUpper.end())break;
continue;
}
break;
while(dropsBeforeUpperIt!=dropsBeforeUpper.end()){
const ItemDrop&drop=ItemDrop::drops[*dropsBeforeUpperIt];
drop.Draw();
++dropsBeforeUpperIt;
}
}
if(!player->rendered&&!player->upperLevel&&player->GetPos().y<topTileY){
player->rendered=true;
if(player->GetZ()>0){
vf2d shadowScale=vf2d{8*player->GetSizeMult()/3.f,1}/std::max(1.f,player->GetZ()/24);
@ -1707,45 +1606,22 @@ void AiL::RenderWorld(float fElapsedTime){
}
RenderPlayer(player->GetPos(),{1,1});
}
{
auto it=monstersAfterUpper.begin();
while(it!=monstersAfterUpper.end()){
Monster&m=**it;
if(m.pos.y<topTileY){
m.Draw();
it=monstersAfterUpper.erase(it);
if(it==monstersAfterUpper.end())break;
continue;
}
break;
}
}
{
auto it=dropsAfterUpper.begin();
while(it!=dropsAfterUpper.end()){
const ItemDrop&drop=ItemDrop::drops[*it];
if(drop.pos.y<topTileY){
drop.Draw();
it=dropsAfterUpper.erase(it);
if(it==dropsAfterUpper.end())break;
continue;
}
break;
while(monstersAfterUpperIt!=monstersAfterUpper.end()){
Monster&m=**monstersAfterUpperIt;
if(m.pos.y<topTileY){
m.Draw();
++monstersAfterUpperIt;
continue;
}
break;
}
{
auto it=foregroundEffectsUpper.begin();
while(it!=foregroundEffectsUpper.end()){
const Effect&e=**it;
if(e.pos.y<topTileY){
e.Draw();
it=foregroundEffectsUpper.erase(it);
if(it==foregroundEffectsUpper.end())break;
if(it!=foregroundEffectsUpper.begin())--it;
continue;
}
break;
while(dropsAfterUpperIt!=dropsAfterUpper.end()){
const ItemDrop&drop=ItemDrop::drops[*dropsAfterUpperIt];
if(drop.pos.y<topTileY){
drop.Draw();
continue;
}
break;
}
#pragma endregion
}
@ -1753,59 +1629,36 @@ void AiL::RenderWorld(float fElapsedTime){
#pragma region Upper Foreground Rendering w/Depth
for(TileRenderData*tile:tilesWithCollision){
#pragma region Depth Ordered Upper Rendering
{
auto it=monstersBeforeUpper.begin();
while(it!=monstersBeforeUpper.end()){
Monster&m=**it;
if(m.pos.y<tile->group->GetCollisionRange().middle().y){
m.Draw();
it=monstersBeforeUpper.erase(it);
if(it==monstersBeforeUpper.end())break;
continue;
}
break;
while(monstersBeforeUpperIt!=monstersBeforeUpper.end()){
Monster&m=**monstersBeforeUpperIt;
if(m.pos.y<tile->group->GetCollisionRange().middle().y){
m.Draw();
++monstersBeforeUpperIt;
continue;
}
break;
}
{
auto it=bulletsUpper.begin();
while(it!=bulletsUpper.end()){
const Bullet&b=**it;
if(b.pos.y<tile->group->GetCollisionRange().middle().y){
b.Draw();
it=bulletsUpper.erase(it);
if(it==bulletsUpper.end())break;
continue;
}
break;
while(dropsBeforeUpperIt!=dropsBeforeUpper.end()){
const ItemDrop&drop=ItemDrop::drops[*dropsBeforeUpperIt];
if(drop.pos.y<tile->group->GetCollisionRange().middle().y){
drop.Draw();
++dropsBeforeUpperIt;
continue;
}
break;
}
{
auto it=backgroundEffectsUpper.begin();
while(it!=backgroundEffectsUpper.end()){
const Effect&e=**it;
if(e.pos.y<tile->group->GetCollisionRange().middle().y){
e.Draw();
it=backgroundEffectsUpper.erase(it);
if(it==backgroundEffectsUpper.end())break;
continue;
}
break;
if(!player->rendered&&player->upperLevel&&player->GetPos().y<tile->group->GetCollisionRange().middle().y){
//If we are supposed to render the player, everything else before must be rendered at this point.
while(monstersBeforeUpperIt!=monstersBeforeUpper.end()){
Monster&m=**monstersBeforeUpperIt;
m.Draw();
++monstersBeforeUpperIt;
}
}
{
auto it=dropsBeforeUpper.begin();
while(it!=dropsBeforeUpper.end()){
const ItemDrop&drop=ItemDrop::drops[*it];
if(drop.pos.y<tile->group->GetCollisionRange().middle().y){
drop.Draw();
it=dropsBeforeUpper.erase(it);
if(it==dropsBeforeUpper.end())break;
continue;
}
break;
while(dropsBeforeUpperIt!=dropsBeforeUpper.end()){
const ItemDrop&drop=ItemDrop::drops[*dropsBeforeUpperIt];
drop.Draw();
++dropsBeforeUpperIt;
}
}
if(!player->rendered&&player->upperLevel&&player->GetPos().y<tile->group->GetCollisionRange().middle().y){
player->rendered=true;
if(player->GetZ()>0){
vf2d shadowScale=vf2d{8*player->GetSizeMult()/3.f,1}/std::max(1.f,player->GetZ()/24);
@ -1813,44 +1666,23 @@ void AiL::RenderWorld(float fElapsedTime){
}
RenderPlayer(player->GetPos(),{1,1});
}
{
auto it=monstersAfterUpper.begin();
while(it!=monstersAfterUpper.end()){
Monster&m=**it;
if(m.pos.y<tile->group->GetCollisionRange().middle().y){
m.Draw();
it=monstersAfterUpper.erase(it);
if(it==monstersAfterUpper.end())break;
continue;
}
break;
}
}
{
auto it=dropsAfterUpper.begin();
while(it!=dropsAfterUpper.end()){
const ItemDrop&drop=ItemDrop::drops[*it];
if(drop.pos.y<tile->group->GetCollisionRange().middle().y){
drop.Draw();
it=dropsAfterUpper.erase(it);
if(it==dropsAfterUpper.end())break;
continue;
}
break;
while(monstersAfterUpperIt!=monstersAfterUpper.end()){
Monster&m=**monstersAfterUpperIt;
if(m.pos.y<tile->group->GetCollisionRange().middle().y){
m.Draw();
++monstersAfterUpperIt;
continue;
}
break;
}
{
auto it=foregroundEffectsUpper.begin();
while(it!=foregroundEffectsUpper.end()){
const Effect&e=**it;
if(e.pos.y<tile->group->GetCollisionRange().middle().y){
e.Draw();
it=foregroundEffectsUpper.erase(it);
if(it==foregroundEffectsUpper.end())break;
continue;
}
break;
while(dropsAfterUpperIt!=dropsAfterUpper.end()){
const ItemDrop&drop=ItemDrop::drops[*dropsAfterUpperIt];
if(drop.pos.y<tile->group->GetCollisionRange().middle().y){
drop.Draw();
++dropsAfterUpperIt;
continue;
}
break;
}
#pragma endregion
RenderTile(*tile,{255,255,255,uint8_t(255-tile->tileOpacity/TileGroup::FADE_TIME*TileGroup::FADE_AMT)});
@ -1872,9 +1704,6 @@ void AiL::RenderWorld(float fElapsedTime){
for(const Effect*const e:backgroundEffectsUpper){
e->Draw();
}
for(const Bullet*const b:bulletsUpper){
b->Draw();
}
for(const int dropInd:dropsBeforeUpper){
ItemDrop::drops[dropInd].Draw();
}
@ -1893,6 +1722,9 @@ void AiL::RenderWorld(float fElapsedTime){
for(const int dropInd:dropsAfterUpper){
ItemDrop::drops[dropInd].Draw();
}
for(const Bullet*const b:bulletsUpper){
b->Draw();
}
for(const Effect*const e:foregroundEffectsUpper){
e->Draw();
}
@ -2130,6 +1962,8 @@ void AiL::RenderHud(){
}
#endif
hudOverlay.Draw();
Pixel vignetteOverlayColor="Interface.Vignette Color"_Pixel;
const float vignetteTotalDisplayTime="Interface.Vignette Appearance Time"_F+"Interface.Vignette Fadeout Time"_F;
if(vignetteDisplayTime<"Interface.Vignette Fadeout Time"_F)vignetteOverlayColor.a=util::lerp(0,255,vignetteDisplayTime/"Interface.Vignette Fadeout Time"_F);
@ -2431,6 +2265,7 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
MONSTER_LIST.clear();
BULLET_LIST.clear();
DAMAGENUMBER_LIST.clear();
hudOverlay.Reset();
backgroundEffects.clear();
foregroundEffects.clear();
ItemDrop::drops.clear();
@ -4431,3 +4266,11 @@ void AiL::AMonsterIsMarkedForDeletion(){
void AiL::SetBossIndicatorPos(const vf2d pos){
bossIndicatorPos=pos;
}
Overlay&AiL::GetOverlay(){
return hudOverlay;
}
void AiL::SetOverlay(std::string animationName,Pixel overlayCol){
hudOverlay=Overlay{animationName,overlayCol};
}

@ -57,7 +57,7 @@ All rights reserved.
#include "DynamicCounter.h"
#include "UndefKeys.h"
#include "Minimap.h"
#include "Overlay.h"
class SteamKeyboardCallbackHandler;
class SteamStatsReceivedHandler;
@ -208,6 +208,7 @@ private:
SteamKeyboardCallbackHandler*steamKeyboardCallbackListener=nullptr;
SteamStatsReceivedHandler*steamStatsReceivedHandlerListener=nullptr;
std::optional<vf2d>bossIndicatorPos{};
Overlay hudOverlay{"pixel.png",BLANK};
public:
AiL();
bool OnUserCreate() override;
@ -348,6 +349,8 @@ public:
Minimap minimap;
void AMonsterIsMarkedForDeletion(); //The way this is implemented is that monsters marked for deletion will cause the monster update loop to detect there's at least one or more monsters that must be deleted and will call erase_if on the list at the end of the iteration loop.
void SetBossIndicatorPos(const vf2d pos);
void SetOverlay(std::string animationName,Pixel overlayCol);
Overlay&GetOverlay();
struct TileGroupData{
vi2d tilePos;

@ -384,6 +384,15 @@ Direction Monster::GetFacingDirection()const{
return facingDirection;
}
void Monster::UpdateFacingDirection(Direction newFacingDir){
if(HasFourWaySprites()){
facingDirection=newFacingDir;
}else{
if(newFacingDir==Direction::NORTH||newFacingDir==Direction::SOUTH)ERR(std::format("WARNING! Trying to set a facing direction of {} for Monster {}! Not possible because the monster does not have four-way facing sprites!",int(newFacingDir),GetDisplayName()));
facingDirection=newFacingDir;
}
}
void Monster::UpdateFacingDirection(vf2d facingTargetPoint){
if(Immovable())return;
float facingAngle=util::angleTo(GetPos(),facingTargetPoint);

@ -95,6 +95,7 @@ public:
Direction GetFacingDirection()const;
//Will make the monster face in the correct direction relative to a given target point to look at.
void UpdateFacingDirection(vf2d facingTargetPoint);
void UpdateFacingDirection(Direction newFacingDir);
void Draw()const;
void DrawReflection(float drawRatioX,float multiplierX);
void Collision(Player*p);
@ -262,7 +263,7 @@ private:
static float _GetFloat(Monster&m,std::string param,std::string strategy,int index=0);
static Pixel _GetPixel(Monster&m,std::string param,std::string strategy,int index=0);
//Converts unit distances to pixels. (Every 100 units = 24 pixels)
static double _GetPixels(Monster&m,std::string param,std::string strategy,int index=0);
static float _GetPixels(Monster&m,std::string param,std::string strategy,int index=0);
static vf2d _GetVec(Monster&m,std::string param,std::string strategy,int index=0);
static const std::string&_GetString(Monster&m,std::string param,std::string strategy,int index=0);
static const datafile&_Get(Monster&m,std::string param,std::string strategy);

@ -0,0 +1,68 @@
#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 © 2024 The FreeType
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
All rights reserved.
*/
#pragma endregion
#include "DEFINES.h"
#include "AdventuresInLestoria.h"
#include "Overlay.h"
INCLUDE_game
INCLUDE_ANIMATION_DATA
Overlay::Overlay(std::string animationName,Pixel overlayCol)
:animationName(animationName),overlayCol(overlayCol){}
const Pixel&Overlay::GetOverlayCol()const{
return overlayCol;
}
void Overlay::SetOverlayCol(Pixel newOverlayCol){
overlayCol=newOverlayCol;
}
void Overlay::Enable(){
enabled=true;
}
void Overlay::Disable(){
enabled=false;
}
void Overlay::Draw(){
if(!enabled)return;
const Animate2D::Frame&animationFrame{ANIMATION_DATA.at(animationName).GetFrame(game->GetRunTime())};
game->DrawPartialDecal({},animationFrame.GetSourceRect().size,animationFrame.GetSourceImage()->Decal(),animationFrame.GetSourceRect().pos,animationFrame.GetSourceRect().size,overlayCol);
}
void Overlay::Reset(){
animationName="pixel.png";
overlayCol=BLANK;
}

@ -0,0 +1,56 @@
#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 © 2024 The FreeType
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
All rights reserved.
*/
#pragma endregion
#pragma once
#include "olcPixelGameEngine.h"
class Overlay{
friend class AiL;
public:
Overlay(std::string animationName,Pixel overlayCol);
const Pixel&GetOverlayCol()const;
void SetOverlayCol(Pixel newOverlayCol);
void Enable();
void Disable();
private /*AiL*/:
void Draw();
void Reset();
private:
bool enabled{true};
std::string animationName;
Pixel overlayCol;
};

@ -154,7 +154,7 @@ Pixel Monster::STRATEGY::_GetPixel(Monster&m,std::string param,std::string strat
}
}
double Monster::STRATEGY::_GetPixels(Monster&m,std::string param,std::string strategy,int index){
float Monster::STRATEGY::_GetPixels(Monster&m,std::string param,std::string strategy,int index){
if(m.IsNPC()&&DATA["NPCs"][m.name].HasProperty(param)){
return DATA["NPCs"][m.name].GetProperty(param).GetReal(index)/100.f*24;
}else

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 1
#define VERSION_MINOR 2
#define VERSION_PATCH 3
#define VERSION_BUILD 9473
#define VERSION_BUILD 9482
#define stringify(a) stringify_(a)
#define stringify_(a) #a

@ -55,6 +55,8 @@ void Monster::STRATEGY::ZEPHY(Monster&m,float fElapsedTime,std::string strategy)
FLY_ACROSS,
TORNADO_ATTACK_PREPARE,
TORNADO_ATTACK,
WIND_ATTACK_FLY,
WIND_ATTACK_LAND,
WIND_ATTACK,
HALFHEALTH_PHASE,
};
@ -71,13 +73,22 @@ void Monster::STRATEGY::ZEPHY(Monster&m,float fElapsedTime,std::string strategy)
m.F(A::SPAWNER_TIMER)=ConfigFloat("Basic Hawk Spawn Time");
}
#pragma region Flying Hover Effect
if(m.F(A::TARGET_FLYING_HEIGHT)==0.f)m.SetZ(std::max(m.F(A::FLYING_HEIGHT),0.f));
else m.SetZ(std::max(m.F(A::FLYING_HEIGHT)+ConfigFloat("Flight Oscillation Amount")*sin((PI*m.TimeSpentAlive())/1.5f),0.f));
#pragma endregion
if(m.F(A::FLYING_HEIGHT)<m.F(A::TARGET_FLYING_HEIGHT))m.F(A::FLYING_HEIGHT)=std::min(m.F(A::TARGET_FLYING_HEIGHT),m.F(A::FLYING_HEIGHT)+ConfigPixels("Fly Rise/Fall Speed")*fElapsedTime);
else if(m.F(A::FLYING_HEIGHT)>-ConfigFloat("Flight Oscillation Amount"))m.F(A::FLYING_HEIGHT)=std::max(-ConfigFloat("Flight Oscillation Amount"),m.F(A::FLYING_HEIGHT)-ConfigPixels("Fly Rise/Fall Speed")*fElapsedTime);
switch(m.phase){
case INITIALIZE:{
m.F(A::SPAWNER_TIMER)=ConfigFloat("Basic Hawk Spawn Time");
m.phase=IDLE;
game->SetOverlay(ConfigString("Wind Attack.Wind Overlay Sprite"),ConfigPixel("Wind Attack.Wind Overlay Color"));
game->GetOverlay().Disable();
}break;
case IDLE:{
const int randomAttackChoice=util::random()%2;
const int randomAttackChoice=util::random()%3;
switch(randomAttackChoice){
case 0:{
@ -94,10 +105,12 @@ void Monster::STRATEGY::ZEPHY(Monster&m,float fElapsedTime,std::string strategy)
m.target=ConfigVec("Tornado Attack.Landing Area");
}break;
case 2:{
m.phase=WIND_ATTACK;
}break;
case 3:{
m.phase=HALFHEALTH_PHASE;
m.phase=WIND_ATTACK_FLY;
m.F(A::TARGET_FLYING_HEIGHT)=ConfigPixels("Wind Attack.Fly Up Height");
const bool LeftLandingSite=m.I(A::ATTACK_CHOICE)=util::random()%2;
if(LeftLandingSite)m.target=ConfigVec("Wind Attack.Left Landing Site");
else m.target=ConfigVec("Wind Attack.Right Landing Site");
}break;
}
}break;
@ -173,8 +186,24 @@ void Monster::STRATEGY::ZEPHY(Monster&m,float fElapsedTime,std::string strategy)
m.F(A::CASTING_TIMER)-=fElapsedTime;
if(m.F(A::CASTING_TIMER)<=0.f)m.phase=IDLE;
}break;
case WIND_ATTACK_FLY:{
m.targetAcquireTimer=20.f;
RUN_TOWARDS(m,fElapsedTime,"Run Towards");
if(m.ReachedTargetPos()){
m.phase=WIND_ATTACK_LAND;
m.F(A::TARGET_FLYING_HEIGHT)=0.f;
}
}break;
case WIND_ATTACK_LAND:{
if(m.GetZ()==0.f){
m.phase=WIND_ATTACK;
game->GetOverlay().Enable();
}
}break;
case WIND_ATTACK:{
const bool OnLeftLandingSite=m.I(A::ATTACK_CHOICE);
if(OnLeftLandingSite)m.PerformAnimation("ATTACK",Direction::EAST);
else m.PerformAnimation("ATTACK",Direction::WEST);
}break;
case HALFHEALTH_PHASE:{

@ -780,6 +780,11 @@ MonsterStrategy
Basic Hawk Spawn Time = 10s
Basic Hawk Spawn Radius = 1000
# In units/sec
Fly Rise/Fall Speed = 400
Flight Oscillation Amount = 1.5px
Fly Across Attack
{
Poop Damage = 25
@ -819,5 +824,16 @@ MonsterStrategy
Ring 6 = 775, 18, -7
}
}
Wind Attack
{
# In Units
Fly Up Height = 700
Left Landing Site = 1608, 1728
Right Landing Site = 2472, 1728
Wind Overlay Sprite = "wind_vignette.png"
Wind Overlay Color = 64, 64, 64, 255
}
}
}

@ -99,6 +99,7 @@ Images
GFX_BossIndicator = bossIndicator.png
GFX_BirdPoop = birdpoop.png
GFX_Tornado = tornado2.png
GFX_WindOverlay = wind_vignette.png
# Ability Icons
GFX_Warrior_BattleCry_Icon = Ability Icons/battlecry.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 916 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Loading…
Cancel
Save