Setup second chapter boss spawn group, template, and map. Fix issues with being able to click stage plates that were hidden behind the menu or off-screen. Fix crash when item drops spawn in a certain position. Release Build 9585.

removeExposedPackKey
sigonasr2 8 months ago
parent c738bdac0b
commit 01df50e8da
  1. 6
      Adventures in Lestoria/AdventuresInLestoria.cpp
  2. 12
      Adventures in Lestoria/Bear.cpp
  3. 5
      Adventures in Lestoria/BreakingPillar.cpp
  4. 5
      Adventures in Lestoria/Menu.cpp
  5. 1
      Adventures in Lestoria/Menu.h
  6. 4
      Adventures in Lestoria/State_OverworldMap.cpp
  7. 33
      Adventures in Lestoria/StoneGolem.cpp
  8. 2
      Adventures in Lestoria/Version.h
  9. 13
      Adventures in Lestoria/assets/Campaigns/Boss_2.tmx
  10. 16
      Adventures in Lestoria/assets/config/MonsterStrategies.txt
  11. 2
      Adventures in Lestoria/assets/config/Monsters.txt
  12. 3
      Adventures in Lestoria/assets/maps/Monster_Presets.tmx
  13. 5
      Adventures in Lestoria/assets/maps/Monsters/Stone Golem.tx
  14. BIN
      Adventures in Lestoria/assets/maps/monsters-tileset.png
  15. 2
      Adventures in Lestoria/config.h
  16. 6
      Adventures in Lestoria/olcUTIL_DataFile.h
  17. BIN
      x64/Release/Adventures in Lestoria.exe

@ -1434,6 +1434,7 @@ void AiL::RenderWorld(float fElapsedTime){
while(dropsAfterLowerIt!=dropsAfterLower.end()){
const int dropInd=*dropsAfterLowerIt;
ItemDrop::drops[dropInd].Draw();
++dropsAfterLowerIt;
}
for(const Bullet*const b:bulletsLower){
b->_Draw();
@ -3164,6 +3165,11 @@ datafile operator ""_A(const char*key,std::size_t len){
return DATA.GetProperty(std::string(key,len));
}
vf2d operator ""_V(const char*key,std::size_t len){
AiL::OutputDebugInfo(key,len);
return DATA.GetProperty(std::string(key,len)).GetVf2d();
}
void AiL::OutputDebugInfo(const char*key,std::size_t len){
#ifdef _DEBUG
if(utils::datafile::DEBUG_ACCESS_OPTIONS){

@ -59,13 +59,14 @@ void Monster::STRATEGY::BEAR(Monster&m,float fElapsedTime,std::string strategy){
m.I(A::PHASE)=1;
m.PerformShootAnimation();
m.F(A::CASTING_TIMER)=ConfigFloat("Chargeup Time");
m.V(A::LOCKON_POS)=game->GetPlayer()->GetPos();
//The bear slam attack indicator will move with the bear, and the LOCKON_POS variable will hold a polar coordinate indicating distance and angle for where it should be attacking relative to its position.
m.V(A::LOCKON_POS)=vf2d{distToPlayer,util::angleTo(m.GetPos(),game->GetPlayer()->GetPos())};
m.SetStrategyDrawFunction([](AiL*game,Monster&m,const std::string&strategy){
if(m.IsAlive()){
game->view.DrawRotatedDecal(m.V(A::LOCKON_POS),GFX["range_indicator.png"].Decal(),0.f,{12.f,12.f},vf2d{ConfigFloat("Smash Attack Diameter"),ConfigFloat("Smash Attack Diameter")}/100.f,{255,255,0,160});
game->view.DrawRotatedDecal(m.GetPos()+m.V(A::LOCKON_POS).cart(),GFX["range_indicator.png"].Decal(),0.f,{12.f,12.f},vf2d{ConfigFloat("Smash Attack Diameter"),ConfigFloat("Smash Attack Diameter")}/100.f,{255,255,0,160});
}
});
m.RotateTowardsPos(m.V(A::LOCKON_POS));
m.RotateTowardsPos(m.GetPos()+m.V(A::LOCKON_POS).cart());
}else{
m.target=game->GetPlayer()->GetPos();
RUN_TOWARDS(m,fElapsedTime,"Run Towards");
@ -82,10 +83,11 @@ void Monster::STRATEGY::BEAR(Monster&m,float fElapsedTime,std::string strategy){
case 2:{
m.F(A::CASTING_TIMER)=std::max(0.f,m.F(A::CASTING_TIMER)-fElapsedTime);
if(m.F(A::CASTING_TIMER)==0.f){
SoundEffect::PlaySFX("Bear Slam Attack",m.V(A::LOCKON_POS));
float distToPlayer=geom2d::line<float>(m.GetPos(),game->GetPlayer()->GetPos()).length();
SoundEffect::PlaySFX("Bear Slam Attack",m.GetPos()+m.V(A::LOCKON_POS).cart());
m.I(A::PHASE)=0;
m.I(A::BEAR_STOMP_COUNT)++;
geom2d::circle<float>attackCircle={m.V(A::LOCKON_POS),float(operator""_Pixels(ConfigFloat("Smash Attack Diameter"))/2.f)};
geom2d::circle<float>attackCircle={m.GetPos()+m.V(A::LOCKON_POS).cart(),float(operator""_Pixels(ConfigFloat("Smash Attack Diameter"))/2.f)};
if(geom2d::overlaps(attackCircle,game->GetPlayer()->Hitbox())){
if(game->GetPlayer()->Hurt(m.GetAttack(),m.OnUpperLevel(),0.f)){
game->GetPlayer()->Knockup(ConfigFloat("Attack Knockup Duration"));

@ -43,11 +43,6 @@ All rights reserved.
using A=Attribute;
void Monster::STRATEGY::BREAKING_PILLAR(Monster&m,float fElapsedTime,std::string strategy){
enum PhaseName{
INITIALIZE,
IDLE,
};
if(m.GetHealthRatio()>=ConfigFloat("Break Phase 1 HP % Threshold")/100.f){
m.animation.ModifyDisplaySprite(m.internal_animState,ConfigString("Unbroken Animation Name"));
}else

@ -795,4 +795,9 @@ void Menu::ReInitializeInputGroup(){
const bool Menu::GameInitialized()const{
return game->GameInitialized();
}
const bool Menu::IsMouseOverMenu(){
if(Menu::stack.size()==0)return false;
return geom2d::overlaps(game->GetMousePos(),geom2d::rect<float>{Menu::stack.back()->pos-"Interface.9PatchSize"_V.x,Menu::stack.back()->size+"Interface.9PatchSize"_V.y*2});
}

@ -202,6 +202,7 @@ public:
static void IgnoreNextMouseNavigationAttempt();
//Returns whether or not this menu type is currently in the foreground of the game, and thus being interacted with by the user.
static bool IsCurrentlyActive(MenuType type);
static const bool IsMouseOverMenu(); //Returns whether the mouse is hovering over any portion of the menu, thus can be used if a menu is not supposed to cover up everything to determine mouse interactions.
private:
Menu(vf2d pos,vf2d size);
static MenuType lastMenuTypeCreated;

@ -110,7 +110,7 @@ void State_OverworldMap::OnUserUpdate(AiL*game){
if(game->GetMouse(Mouse::LEFT).bPressed&&geom2d::overlaps(game->GetWorldMousePos(),cp.rect)
||game->KEY_LEFT.Pressed()||game->KEY_RIGHT.Pressed()||game->KEY_UP.Pressed()||game->KEY_DOWN.Pressed()
||(!analogMove&&(abs(game->KEY_SCROLLHORZ_L.Analog())>=0.2f||abs(game->KEY_SCROLLVERT_L.Analog())>=0.2f))){
bool mouseUsed=game->GetMouse(Mouse::LEFT).bPressed&&geom2d::overlaps(game->GetWorldMousePos(),cp.rect);
bool mouseUsed=game->GetMouse(Mouse::LEFT).bPressed&&geom2d::overlaps(game->GetWorldMousePos(),cp.rect)&&!Menu::IsMouseOverMenu()&&game->IsMouseInsideWindow();
if(Unlock::IsUnlocked(cp)){
if(mouseUsed){
@ -193,7 +193,7 @@ void State_OverworldMap::Draw(AiL*game){
}
bool highlightedAStage=false;
for(ConnectionPoint&cp:connections){
if(Unlock::IsUnlocked(cp)&&geom2d::overlaps(game->GetWorldMousePos(),cp.rect)){
if(Unlock::IsUnlocked(cp)&&geom2d::overlaps(game->GetWorldMousePos(),cp.rect)&&!Menu::IsMouseOverMenu()&&game->IsMouseInsideWindow()){
drawutil::DrawCrosshairDecalTransformedView(game->view,cp.rect,currentTime);
highlightedAStage=true;
break;

@ -40,6 +40,7 @@ All rights reserved.
#include "MonsterStrategyHelpers.h"
#include "AdventuresInLestoria.h"
#include "DEFINES.h"
#include "util.h"
INCLUDE_game
@ -48,13 +49,43 @@ using A=Attribute;
void Monster::STRATEGY::STONE_GOLEM(Monster&m,float fElapsedTime,std::string strategy){
enum PhaseName{
INITIALIZE,
SPAWN_PILLAR_PREPARE,
SPAWN_PILLAR_CAST,
STANDARD,
};
switch(m.phase){
case INITIALIZE:{
m.F(A::RECOVERY_TIME)=ConfigFloat("Beginning Phase.Pillar Cast Delay Time");
m.I(A::PATTERN_REPEAT_COUNT)=ConfigInt("Beginning Phase.Repeat Count");
m.phase=SPAWN_PILLAR_PREPARE;
}break;
case SPAWN_PILLAR_PREPARE:{
m.F(A::RECOVERY_TIME)-=fElapsedTime;
if(m.F(A::RECOVERY_TIME)<=0.f){
m.V(A::LOCKON_POS)=game->GetPlayer()->GetPos();
m.PerformAnimation("STONE PILLAR CAST",m.GetFacingDirectionToTarget(m.V(A::LOCKON_POS)));
game->AddEffect(std::make_unique<Effect>(m.V(A::LOCKON_POS),ConfigFloat("Beginning Phase.Pillar Cast Time"),"range_indicator.png",m.OnUpperLevel(),vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Golem Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Golem Pillar").GetSizeMult()/12.f)*1.25f,0.3f,vf2d{},ConfigPixel("Beginning Phase.Pillar Spell Circle Color"),util::random(2*PI),util::degToRad(ConfigFloat("Beginning Phase.Pillar Spell Circle Rotation Spd"))),true);
game->AddEffect(std::make_unique<Effect>(m.V(A::LOCKON_POS),ConfigFloat("Beginning Phase.Pillar Cast Time"),"spell_insignia.png",m.OnUpperLevel(),vf2d{1.f,1.f}*(MONSTER_DATA.at("Stone Golem Pillar").GetCollisionRadius()*MONSTER_DATA.at("Stone Golem Pillar").GetSizeMult()/12.f)*0.9f,0.3f,vf2d{},ConfigPixel("Beginning Phase.Pillar Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Beginning Phase.Pillar Spell Insignia Rotation Spd"))),true);
m.F(A::CASTING_TIMER)=ConfigFloat("Beginning Phase.Pillar Cast Time");
m.phase=SPAWN_PILLAR_CAST;
}
}break;
case SPAWN_PILLAR_CAST:{
m.F(A::CASTING_TIMER)-=fElapsedTime;
if(m.F(A::CASTING_TIMER)<=0.f){
m.PerformAnimation("STONE PILLAR CAST",m.GetFacingDirectionToTarget(game->GetPlayer()->GetPos()));
m.I(A::PATTERN_REPEAT_COUNT)--;
if(m.I(A::PATTERN_REPEAT_COUNT)<=0){
m.phase=STANDARD;
}else{
m.PerformIdleAnimation(m.GetFacingDirectionToTarget(game->GetPlayer()->GetPos()));
m.F(A::RECOVERY_TIME)=ConfigFloat("Beginning Phase.Pillar Cast Delay Time");
m.phase=SPAWN_PILLAR_PREPARE;
}
}
}break;
case STANDARD:{
}break;
}
}

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 1
#define VERSION_MINOR 2
#define VERSION_PATCH 3
#define VERSION_BUILD 9578
#define VERSION_BUILD 9585
#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="64" height="89" tilewidth="24" tileheight="24" infinite="0" nextlayerid="6" nextobjectid="4">
<map version="1.10" tiledversion="1.10.2" class="Map" orientation="orthogonal" renderorder="right-down" width="64" height="89" tilewidth="24" tileheight="24" infinite="0" nextlayerid="6" nextobjectid="6">
<properties>
<property name="Backdrop" propertytype="Backdrop" value="mountain_night"/>
<property name="Background Music" propertytype="BGM" value="foresty_boss"/>
@ -385,5 +385,16 @@
<objectgroup id="5" name="Spawn Zones">
<object id="1" name="Boss Arena" type="BossArena" x="216" y="216" width="696" height="498"/>
<object id="2" name="Player Spawn" type="PlayerSpawnLocation" x="552" y="672" width="24" height="24"/>
<object id="4" name="Stone Golem Spawn" type="SpawnGroup" x="246" y="276" width="636" height="390">
<properties>
<property name="Boss Title Display" value="Stone Golem"/>
</properties>
<ellipse/>
</object>
<object id="5" template="../maps/Monsters/Stone Golem.tx" x="468" y="474">
<properties>
<property name="spawner" type="object" value="4"/>
</properties>
</object>
</objectgroup>
</map>

@ -886,7 +886,7 @@ MonsterStrategy
6 monsters = 2/s
5 monsters = 2.5/s
4 monsters = 3/s
3 monsters = 3.5/s
3 monsters = 3.5/s(
2 monsters = 4/s
1 monster = 4.5/s
}
@ -898,7 +898,19 @@ MonsterStrategy
}
Stone Golem
{
Beginning Phase
{
# Number of pillars to spawn.
Repeat Count = 3
Pillar Cast Time = 2s
Pillar Cast Delay Time = 0.5s
Pillar Spell Circle Color = 40, 40, 40, 80
Pillar Spell Insignia Color = 144, 137, 160, 255
# Degrees/sec. Positive is CW, Negative is CCW.
Pillar Spell Circle Rotation Spd = -30
# Degrees/sec. Positive is CW, Negative is CCW.
Pillar Spell Insignia Rotation Spd = 50
}
}
Breaking Pillar
{

@ -1061,7 +1061,7 @@ Monsters
NORMAL = 4, 0.4, OneShot
BREAK1 = 4, 0.4, OneShot
BREAK2 = 4, 0.4, OneShot
DEATH = 1, 0.15, OneShot
CRUMBLE = 6, 0.3, OneShot
}
Hurt Sound = Warrior Ground Slam

@ -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="29">
<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="30">
<tileset firstgid="1" source="Monsters.tsx"/>
<layer id="1" name="Tile Layer 1" width="30" height="20">
<data encoding="csv"/>
@ -26,5 +26,6 @@
<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"/>
<object id="29" template="Monsters/Stone Golem.tx" type="Monster" x="174" y="444"/>
</objectgroup>
</map>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<template>
<tileset firstgid="1" source="../Monsters.tsx"/>
<object name="Stone Golem" type="Monster" gid="21" width="192" height="192"/>
</template>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

@ -62,6 +62,8 @@ int operator ""_I(const char*key,std::size_t len);
float operator ""_F(const char*key,std::size_t len);
//Read a double key from the config.
double operator ""_D(const char*key,std::size_t len);
//Read a vf2d key from the config.
vf2d operator ""_V(const char*key,std::size_t len);
//Read a datafile indexed property from the config.
utils::datafile operator ""_A(const char*key,std::size_t len);

@ -129,6 +129,12 @@ namespace olc::utils
return std::atoi(GetString(nItem).c_str());
}
// Retrieves the Integer Value of a Property (for a given index) or 0
inline const vf2d GetVf2d(const size_t nItem = 0) const
{
return {GetReal(0),GetReal(1)};
}
// Retrieves the Boolean Value of a Property (for a given index) or false
inline const bool GetBool(const size_t nItem = 0) const
{

Loading…
Cancel
Save