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.
This commit is contained in:
parent
c738bdac0b
commit
01df50e8da
@ -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:{
|
||||
if(m.F(A::CASTING_TIMER)<=0.f){
|
||||
m.PerformAnimation("STONE PILLAR CAST",m.GetFacingDirectionToTarget(game->GetPlayer()->GetPos()));
|
||||
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.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
|
||||
{
|
||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user