Compare commits
80 Commits
@ -0,0 +1,79 @@ |
||||
#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 "Arc.h" |
||||
#include "AdventuresInLestoria.h" |
||||
|
||||
INCLUDE_game |
||||
|
||||
Arc::Arc(const vf2d pos,const float radius,const float pointingAngle,const float sweepAngle) |
||||
:pos(pos),radius(radius),pointingAngle(pointingAngle),sweepAngle(sweepAngle){ |
||||
if(sweepAngle<0.f)ERR(std::format("WARNING! Sweep angle must be greater than or equal to 0! Provided Sweep Angle: {}",sweepAngle)); |
||||
GenerateArc(); |
||||
} |
||||
void Arc::Draw(AiL*game,const Pixel col){ |
||||
game->SetDecalStructure(DecalStructure::FAN); |
||||
game->view.DrawPolygonDecal(nullptr,poly.pos,poly.pos,col); |
||||
} |
||||
const bool Arc::overlaps(const vf2d checkPos)const{ |
||||
return geom2d::overlaps(checkPos,poly); |
||||
} |
||||
void Arc::GrowRadius(const float growAmt){ |
||||
radius+=growAmt; |
||||
GenerateArc(); |
||||
} |
||||
void Arc::GenerateArc(){ |
||||
poly.pos.clear(); |
||||
//Use cut-off point between two angles
|
||||
poly.pos.emplace_back(pos); //Always add 0,0
|
||||
float smallestAng{util::radToDeg(pointingAngle-sweepAngle)+90}; |
||||
float largestAng{util::radToDeg(pointingAngle+sweepAngle)+90}; |
||||
while(smallestAng<0.f)smallestAng+=360; |
||||
while(largestAng<0.f)largestAng+=360; |
||||
int startInd{int(std::fmod(smallestAng/4+1,90))}; |
||||
int endInd{int(std::fmod(largestAng/4+1,90))}; |
||||
if(startInd>endInd){ |
||||
startInd=(startInd+3)%90; |
||||
}else{ |
||||
endInd=(endInd+3)%90; |
||||
} |
||||
for(int i=startInd;i!=endInd;i=(i+1)%game->circleCooldownPoints.size()){ |
||||
poly.pos.emplace_back(pos+game->circleCooldownPoints[i]*radius); |
||||
} |
||||
poly.pos.emplace_back(pos); //Connect back to itself.
|
||||
} |
@ -0,0 +1,59 @@ |
||||
#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 "olcUTIL_Geometry2D.h" |
||||
#include "Pixel.h" |
||||
|
||||
class AiL; |
||||
|
||||
class Arc{ |
||||
public: |
||||
//Define a sweep angle such that each direction will arc that way. Example: PI/2 means a sweep angle from -PI/2 to PI/2. MUST BE POSITIVE
|
||||
Arc(const vf2d pos,const float radius,const float pointingAngle,const float sweepAngle); |
||||
void Draw(AiL*game,const Pixel col); |
||||
const bool overlaps(const vf2d checkPos)const; |
||||
void GrowRadius(const float growAmt); |
||||
const vf2d pos; |
||||
const float pointingAngle; |
||||
const float sweepAngle; |
||||
float radius; |
||||
geom2d::polygon<float>poly; |
||||
private: |
||||
void GenerateArc(); |
||||
}; |
@ -0,0 +1,118 @@ |
||||
#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 "MonsterStrategyHelpers.h" |
||||
#include "util.h" |
||||
#include "AdventuresInLestoria.h" |
||||
#include "SoundEffect.h" |
||||
#include "BulletTypes.h" |
||||
|
||||
using A=Attribute; |
||||
|
||||
INCLUDE_game |
||||
|
||||
void Monster::STRATEGY::CRAB(Monster&m,float fElapsedTime,std::string strategy){ |
||||
enum PhaseName{ |
||||
INIT, |
||||
MOVE, |
||||
PREPARE_CHARGE, |
||||
CHARGE, |
||||
}; |
||||
|
||||
switch(PHASE()){ |
||||
case INIT:{ |
||||
m.B(A::RANDOM_DIRECTION)=util::random()%2; |
||||
m.F(A::RANDOM_RANGE)=util::random_range(ConfigPixelsArr("Random Direction Range",0),ConfigPixelsArr("Random Direction Range",1)); |
||||
SETPHASE(MOVE); |
||||
}break;
|
||||
case MOVE:{ |
||||
m.F(A::ATTACK_COOLDOWN)+=fElapsedTime; |
||||
m.F(A::LAST_JUMP_TIMER)+=fElapsedTime; |
||||
|
||||
float distToPlayer=m.GetDistanceFrom(game->GetPlayer()->GetPos()); |
||||
|
||||
const bool outsideMaxShootingRange=distToPlayer>=ConfigPixelsArr("Stand Still and Shoot Range",1); |
||||
|
||||
if(m.F(A::LAST_JUMP_TIMER)>=ConfigFloat("Stop Check Interval")){ |
||||
if(util::random(100)<=ConfigFloat("Stop Percent")){ |
||||
SETPHASE(PREPARE_CHARGE); |
||||
m.PerformAnimation("CHARGEUP",m.GetFacingDirectionToTarget(game->GetPlayer()->GetPos())); |
||||
m.F(A::CASTING_TIMER)=ConfigFloat("Charge Wait Time"); |
||||
m.target=game->GetPlayer()->GetPos()+util::distance(m.GetPos(),game->GetPlayer()->GetPos())*util::pointTo(m.GetPos(),game->GetPlayer()->GetPos()); |
||||
}else |
||||
if(util::random(100)<=ConfigFloat("Change Direction Chance"))m.B(A::RANDOM_DIRECTION)=!m.B(A::RANDOM_DIRECTION); |
||||
m.F(A::LAST_JUMP_TIMER)=0.f; |
||||
}else |
||||
if(outsideMaxShootingRange){ |
||||
m.target=game->GetPlayer()->GetPos(); |
||||
RUN_TOWARDS(m,fElapsedTime,"Run Towards"); |
||||
}else |
||||
if(distToPlayer<ConfigPixels("Run Away Range")){ |
||||
m.target=geom2d::line<float>(m.GetPos(),game->GetPlayer()->GetPos()).upoint(-1); |
||||
RUN_TOWARDS(m,fElapsedTime,"Run Towards"); |
||||
}else |
||||
if(distToPlayer>=ConfigPixelsArr("Random Direction Range",0)&&distToPlayer<ConfigPixelsArr("Random Direction Range",1)){ |
||||
#define CW true |
||||
#define CCW false |
||||
//We are going to walk in a circular direction either CW or CCW (determined in windup phase)
|
||||
float dirFromPlayer=util::angleTo(game->GetPlayer()->GetPos(),m.GetPos()); |
||||
float targetDir=m.B(A::RANDOM_DIRECTION)==CW?dirFromPlayer+PI/4:dirFromPlayer-PI/4; |
||||
m.target=game->GetPlayer()->GetPos()+vf2d{m.F(A::RANDOM_RANGE),targetDir}.cart(); |
||||
RUN_TOWARDS(m,fElapsedTime,"Run Towards");
|
||||
m.F(A::CHASE_TIMER)=1.f; |
||||
} |
||||
}break; |
||||
case PREPARE_CHARGE:{ |
||||
m.F(A::CASTING_TIMER)-=fElapsedTime; |
||||
if(m.F(A::CASTING_TIMER)<=0.f){ |
||||
SETPHASE(CHARGE); |
||||
m.F(A::CHASE_TIMER)=ConfigFloat("Charge Max Time"); |
||||
m.PerformAnimation("PINCER"); |
||||
} |
||||
}break; |
||||
case CHARGE:{ |
||||
m.F(A::CHASE_TIMER)-=fElapsedTime; |
||||
RUN_TOWARDS(m,fElapsedTime,"Run Towards"); |
||||
if(m.F(A::CHASE_TIMER)<=0.f||m.ReachedTargetPos()){ |
||||
SETPHASE(MOVE); |
||||
m.B(A::RANDOM_DIRECTION)=util::random()%2; |
||||
m.F(A::RANDOM_RANGE)=util::random_range(ConfigPixelsArr("Random Direction Range",0),ConfigPixelsArr("Random Direction Range",1)); |
||||
} |
||||
}break; |
||||
} |
||||
} |
@ -0,0 +1,84 @@ |
||||
#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 "MonsterStrategyHelpers.h" |
||||
#include "util.h" |
||||
#include "AdventuresInLestoria.h" |
||||
#include "SoundEffect.h" |
||||
#include "BulletTypes.h" |
||||
|
||||
using A=Attribute; |
||||
|
||||
INCLUDE_game |
||||
|
||||
void Monster::STRATEGY::GIANT_CRAB(Monster&m,float fElapsedTime,std::string strategy){ |
||||
enum PhaseName{ |
||||
PREPARE_CHARGE, |
||||
CHARGE, |
||||
}; |
||||
switch(PHASE()){ |
||||
case PREPARE_CHARGE:{ |
||||
m.F(A::CASTING_TIMER)-=fElapsedTime; |
||||
if(m.F(A::CASTING_TIMER)<=0.f){ |
||||
m.AddBuff(BuffType::SPEEDBOOST,ConfigFloat("Charge Time"),0.f); |
||||
m.F(A::SPEED_RAMPUP_TIMER)=0.1f; |
||||
SETPHASE(CHARGE); |
||||
} |
||||
}break; |
||||
case CHARGE:{ |
||||
m.F(A::CHASE_TIMER)+=fElapsedTime; |
||||
m.F(A::SPEED_RAMPUP_TIMER)-=fElapsedTime; |
||||
if(m.F(A::CHASE_TIMER)>=ConfigFloat("Charge Time")||m.ReachedTargetPos()){ |
||||
m.F(A::CHASE_TIMER)=0.f; |
||||
m.target=geom2d::line<float>(m.GetPos(),game->GetPlayer()->GetPos()).rpoint(util::distance(m.GetPos(),game->GetPlayer()->GetPos())+ConfigPixels("Charge Extend Distance")); |
||||
m.RemoveBuff(BuffType::SPEEDBOOST); |
||||
m.F(A::CASTING_TIMER)=ConfigFloat("Charge Wait Time"); |
||||
SETPHASE(PREPARE_CHARGE); |
||||
} |
||||
if(m.F(A::SPEED_RAMPUP_TIMER)<=0.f){ |
||||
m.F(A::SPEED_RAMPUP_TIMER)=0.1f; |
||||
if(m.HasBuff(BuffType::SPEEDBOOST)){ |
||||
const float buffIntensity{m.GetBuffs(BuffType::SPEEDBOOST)[0].intensity}; |
||||
m.EditBuff(BuffType::SPEEDBOOST,0).intensity=std::min(buffIntensity+ConfigFloat("Movespeed Rampup Final Amount")/100.f/(ConfigFloat("Movespeed Rampup Time")/0.1f),ConfigFloat("Movespeed Rampup Final Amount")/100.f); |
||||
} |
||||
} |
||||
|
||||
RUN_TOWARDS(m,fElapsedTime,"Run Towards"); |
||||
}break; |
||||
} |
||||
} |
@ -0,0 +1,85 @@ |
||||
#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 "MonsterStrategyHelpers.h" |
||||
#include "util.h" |
||||
#include "AdventuresInLestoria.h" |
||||
#include "SoundEffect.h" |
||||
#include "BulletTypes.h" |
||||
|
||||
using A=Attribute; |
||||
|
||||
INCLUDE_game |
||||
INCLUDE_MONSTER_LIST |
||||
|
||||
void Monster::STRATEGY::GIANT_OCTOPUS(Monster&m,float fElapsedTime,std::string strategy){ |
||||
enum PhaseName{ |
||||
IDENTIFY_ARMS, |
||||
NORMAL, |
||||
}; |
||||
switch(PHASE()){ |
||||
case IDENTIFY_ARMS:{ |
||||
m.F(A::CASTING_TIMER)=util::random_range(ConfigFloatArr("Tentacle Move Timer",0),ConfigFloatArr("Tentacle Move Timer",1)); |
||||
for(std::shared_ptr<Monster>&arm:MONSTER_LIST){ |
||||
const std::string OCTOPUS_ARM_NAME{"Octopus Arm"}; |
||||
if(arm->GetName()==OCTOPUS_ARM_NAME){ |
||||
std::weak_ptr<Monster>armPtr{arm}; |
||||
m.VEC(A::ARM_LIST).emplace_back(armPtr); |
||||
m.VEC(A::ARM_LOCATIONS).emplace_back(armPtr.lock()->GetPos()); |
||||
} |
||||
} |
||||
}break; |
||||
case NORMAL:{ |
||||
m.F(A::CASTING_TIMER)-=fElapsedTime; |
||||
if(m.F(A::CASTING_TIMER)<=0.f){ |
||||
int deadMonsterCount{0}; |
||||
std::vector<vf2d>tempArmLocs; |
||||
for(size_t i=0U;std::any&arm:m.VEC(A::ARM_LIST)){ |
||||
const std::weak_ptr<Monster>&m{std::any_cast<std::weak_ptr<Monster>>(arm)}; |
||||
if(m.expired()||m.lock()->IsDead()){ |
||||
deadMonsterCount++; |
||||
tempArmLocs.emplace_back(std::any_cast<vf2d>(m.lock()->VEC(A::ARM_LOCATIONS))); |
||||
} |
||||
} |
||||
if(deadMonsterCount>0){ |
||||
|
||||
} |
||||
} |
||||
}break; |
||||
} |
||||
} |
@ -0,0 +1,102 @@ |
||||
#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 "AdventuresInLestoria.h" |
||||
#include "BulletTypes.h" |
||||
|
||||
INCLUDE_ITEM_SCRIPTS |
||||
INCLUDE_game |
||||
INCLUDE_ANIMATION_DATA |
||||
|
||||
void ItemInfo::InitializeScripts(){ |
||||
|
||||
ITEM_SCRIPTS["Restore"]=[](AiL*game,std::optional<vf2d>targetingPos,ItemProps props){ |
||||
for(const auto&[propName,buffType]:NameToBuffType){ |
||||
int restoreAmt=props.GetInt(propName); |
||||
|
||||
game->GetPlayer()->AddBuff(BuffRestorationType::ONE_OFF,NameToBuffType.at(propName),0.01f,float(restoreAmt),0.0f); |
||||
if(restoreAmt>0&&props.PropCount(propName)==3){ |
||||
game->GetPlayer()->AddBuff(BuffRestorationType::OVER_TIME,NameToBuffType.at(propName),props.GetFloat(propName,2),float(restoreAmt),props.GetFloat(propName,1)); |
||||
} |
||||
} |
||||
return true; |
||||
}; |
||||
|
||||
for(auto&[key,value]:ItemAttribute::attributes){ |
||||
if(!DATA.GetProperty("ItemScript.Buff").HasProperty(key)){ |
||||
ERR("WARNING! Buff Item Script does not support Buff "<<std::quoted(value.Name())<<"!"); |
||||
} |
||||
} |
||||
|
||||
ITEM_SCRIPTS["Buff"]=[](AiL*game,std::optional<vf2d>targetingPos,ItemProps props){ |
||||
for(auto&[key,value]:ItemAttribute::attributes){ |
||||
float intensity=props.GetFloat(key,0); |
||||
if(intensity==0.f)continue; |
||||
if(ItemAttribute::Get(key).DisplayAsPercent())intensity/=100; |
||||
game->GetPlayer()->AddBuff(BuffType::STAT_UP,props.GetFloat(key,1),intensity,{ItemAttribute::Get(key)}); |
||||
} |
||||
return true; |
||||
}; |
||||
ITEM_SCRIPTS["RestoreDuringCast"]=[](AiL*game,std::optional<vf2d>targetingPos,ItemProps props){ |
||||
for(const auto&[propName,buffType]:NameToBuffType){ |
||||
int restoreAmt=props.GetInt(propName); |
||||
|
||||
game->GetPlayer()->AddBuff(BuffRestorationType::ONE_OFF,NameToBuffType.at(propName),0.01f,float(restoreAmt),0.0f); |
||||
if(restoreAmt>0&&props.PropCount(propName)==3){ |
||||
game->GetPlayer()->AddBuff(BuffRestorationType::OVER_TIME_DURING_CAST,NameToBuffType.at(propName),props.GetFloat(propName,2),float(restoreAmt),props.GetFloat(propName,1)); |
||||
} |
||||
} |
||||
return true; |
||||
}; |
||||
ITEM_SCRIPTS["Projectile"]=[](AiL*game,std::optional<vf2d>targetingPos,ItemProps props){ |
||||
const int projectileDamage{props.GetInt("Base Damage")+int(game->GetPlayer()->GetAttack()*props.GetFloat("Player Damage Mult"))}; |
||||
std::optional<LingeringEffect>lingeringEffect{}; |
||||
if(props.GetFloat("Linger Time")>0.f){ |
||||
const int damage{props.GetInt("Tick Base Damage")+int(props.GetFloat("Tick Player Damage Mult")*game->GetPlayer()->GetAttack())}; |
||||
lingeringEffect.emplace(vf2d{},props.GetString("Lingering Effect"),props.GetString("Lingering Sound"),props.GetFloat("Linger Radius")/100.f*24,damage,props.GetFloat("Tick Rate"),HurtType::MONSTER,props.GetFloat("Linger Time"),5.f,game->GetPlayer()->OnUpperLevel(),1.f,vf2d{},DARK_RED,util::random(2*PI),0.f,false,0.2f, |
||||
[](const Effect&self){ |
||||
return Effect{self.pos,0.5f,"fire_ring.png",self.OnUpperLevel(),util::random_range(0.7f,1.f),0.1f,{},PixelLerp(Pixel(0xF7B752),Pixel(0xE74F30),util::random(1.f)),util::random(2*PI),0.f,true}; |
||||
}); |
||||
} |
||||
CreateBullet(ThrownProjectile)(game->GetPlayer()->GetPos(),targetingPos.value(),props.GetString("Image"),props.GetFloat("Cast Size")/100.f*24,game->GetPlayer()->GetZ(),0.3f,8.f,projectileDamage,game->GetPlayer()->OnUpperLevel(),false,INFINITE,true,WHITE,props.GetFloat("Cast Size")/100.f*vf2d{1.f,1.f},0.f, |
||||
Effect{vf2d{},ANIMATION_DATA.at("explosionframes.png").GetTotalAnimationDuration(),"explosionframes.png",game->GetPlayer()->OnUpperLevel(),props.GetFloat("Cast Size")/100.f*vf2d{1.f,1.f}},props.GetString("Explode Sound Effect"),lingeringEffect)EndBullet; |
||||
return true; |
||||
}; |
||||
|
||||
ITEM_SCRIPTS.SetInitialized(); |
||||
LOG(ITEM_SCRIPTS.size()<<" item scripts have been loaded."); |
||||
} |
@ -0,0 +1,179 @@ |
||||
#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 "MonsterStrategyHelpers.h" |
||||
#include "util.h" |
||||
#include "AdventuresInLestoria.h" |
||||
#include "SoundEffect.h" |
||||
#include "BulletTypes.h" |
||||
#include "Arc.h" |
||||
|
||||
using A=Attribute; |
||||
|
||||
INCLUDE_game |
||||
INCLUDE_MONSTER_LIST |
||||
INCLUDE_MONSTER_DATA |
||||
|
||||
void Monster::STRATEGY::OCTOPUS_ARM(Monster&m,float fElapsedTime,std::string strategy){ |
||||
enum PhaseName{ |
||||
INIT, |
||||
RISE_ANIMATION, |
||||
SEARCH, |
||||
PREPARE_ATTACK, |
||||
ATTACK_ANIMATION, |
||||
ATTACK_RECOVERY, |
||||
SUBMERGE, |
||||
}; |
||||
|
||||
const auto GetAttackArc=[attackRadius=ConfigFloat("Attack Radius"),attackArc=ConfigFloat("Attack Arc")](const Monster&m){ |
||||
return Arc{m.GetPos(),attackRadius/100.f*24,util::dirToAngle(m.GetFacingDirection()),util::degToRad(attackArc)}; |
||||
}; |
||||
|
||||
if(m.ANY(A::STORED_ARC).has_value()){ |
||||
game->DrawShadowStringDecal({100,100},std::format("Stored Arc Active: {}",std::any_cast<Arc>(m.ANY(A::STORED_ARC)).pos.str())); |
||||
const float growthRate=((ConfigFloat("Attack Radius")/100.f*24)/ConfigFloat("Attack Effect Time"))*fElapsedTime; |
||||
std::any_cast<Arc>(m.ANY(A::STORED_ARC)).GrowRadius(growthRate); |
||||
m.F(A::ENVIRONMENT_TIMER)-=fElapsedTime; |
||||
if(m.F(A::ENVIRONMENT_TIMER)<=0.f)m.ANY(A::STORED_ARC).reset(); |
||||
} |
||||
|
||||
switch(PHASE()){ |
||||
case INIT:{ |
||||
if(ConfigFloat("Attack Swing Damage Wait Time")>m.GetAnimation("ATTACKING").GetTotalAnimationDuration())ERR(std::format("The Attack Swing Damage Wait Time ({}s) should not be greater than the total attack time animation duration! ({}s)",ConfigFloat("Attack Swing Damage Wait Time"),m.GetAnimation("ATTACKING").GetTotalAnimationDuration())); |
||||
m.PerformAnimation("RISE",game->GetPlayer()->GetPos()); |
||||
m.F(A::CASTING_TIMER)=m.GetCurrentAnimation().GetTotalAnimationDuration(); |
||||
SETPHASE(RISE_ANIMATION); |
||||
m.SetStrategyDeathFunction([bossDamageOnDeath=ConfigInt("Boss Damage On Death")](GameEvent&event,Monster&m,const StrategyName&strategyName){ |
||||
m.SetStrategyDrawFunction([](AiL*game,Monster&monster,const std::string&strategy){}); |
||||
const std::string GIANT_OCTOPUS_NAME{"Giant Octopus"}; |
||||
const std::string OCTOPUS_ARM_NAME{"Octopus Arm"}; |
||||
|
||||
if(!MONSTER_DATA.count(GIANT_OCTOPUS_NAME))ERR(std::format("WARNING! {} does not exist on the map! THIS SHOULD NOT BE HAPPENING!",GIANT_OCTOPUS_NAME)); |
||||
|
||||
auto boss{std::find_if(MONSTER_LIST.begin(),MONSTER_LIST.end(),[&GIANT_OCTOPUS_NAME](const std::shared_ptr<Monster>&m){ |
||||
return m->GetName()==GIANT_OCTOPUS_NAME; |
||||
})}; |
||||
if(boss!=MONSTER_LIST.end()){ |
||||
Monster&bossMonster{**boss}; |
||||
bossMonster.Hurt(bossDamageOnDeath,m.OnUpperLevel(),m.GetZ()); |
||||
} |
||||
std::for_each(MONSTER_LIST.begin(),MONSTER_LIST.end(),[&OCTOPUS_ARM_NAME,&strategyName](const std::shared_ptr<Monster>&m){ |
||||
if(m->GetName()==OCTOPUS_ARM_NAME){ |
||||
m->PerformAnimation("SUBMERGE"); |
||||
m->SetPhase(strategyName,SUBMERGE); |
||||
m->GetFloat(A::RECOVERY_TIME)=m->GetCurrentAnimation().GetTotalAnimationDuration(); |
||||
} |
||||
}); |
||||
return false; |
||||
}); |
||||
}break; |
||||
case RISE_ANIMATION:{ |
||||
m.F(A::CASTING_TIMER)-=fElapsedTime; |
||||
if(m.F(A::CASTING_TIMER)<=0.f){ |
||||
m.PerformAnimation("IDLE",game->GetPlayer()->GetPos()); |
||||
SETPHASE(SEARCH); |
||||
} |
||||
}break; |
||||
case SEARCH:{ |
||||
if(util::distance(m.GetPos(),game->GetPlayer()->GetPos())<=ConfigFloat("Attack Radius")/100.f*24){ |
||||
SETPHASE(PREPARE_ATTACK); |
||||
|
||||
m.F(A::ATTACK_COOLDOWN)=util::random_range(ConfigFloatArr("Attack Wiggle Time Range",0),ConfigFloatArr("Attack Wiggle Time Range",1)); |
||||
m.PerformAnimation("ATTACK",game->GetPlayer()->GetPos()); |
||||
|
||||
Arc attackArc{GetAttackArc(m)}; |
||||
|
||||
m.SetStrategyDrawFunction([arc=attackArc,&storedArc=m.ANY(A::STORED_ARC),&alphaTimer=m.F(A::ENVIRONMENT_TIMER),attackEffectTime=ConfigFloat("Attack Effect Time")](AiL*game,Monster&monster,const std::string&strategy){ |
||||
const float alphaTimer{float(std::fmod(game->GetRunTime(),2.f))}; |
||||
uint8_t alpha{util::lerp(uint8_t(0),uint8_t(255),alphaTimer)}; |
||||
if(alphaTimer>1.f)alpha=util::lerp(0,255,1-(alphaTimer-1)); |
||||
const_cast<Arc&>(arc).Draw(game,{0,0,255,uint8_t(alpha)}); |
||||
if(storedArc.has_value()){ |
||||
const uint8_t effectAlpha{util::lerp(uint8_t(0),uint8_t(255),alphaTimer/attackEffectTime)}; |
||||
std::any_cast<Arc>(storedArc).Draw(game,{255,255,255,effectAlpha}); |
||||
} |
||||
}); |
||||
} |
||||
}break; |
||||
case PREPARE_ATTACK:{ |
||||
m.F(A::ATTACK_COOLDOWN)-=fElapsedTime; |
||||
if(m.F(A::ATTACK_COOLDOWN)<=0.f){ |
||||
SETPHASE(ATTACK_ANIMATION); |
||||
m.PerformAnimation("ATTACKING"); |
||||
m.F(A::ENVIRONMENT_TIMER)=m.F(A::RECOVERY_TIME)=ConfigFloat("Attack Effect Time"); |
||||
m.F(A::SWING_OCCURRED)=ConfigFloat("Attack Swing Damage Wait Time"); |
||||
} |
||||
}break; |
||||
case ATTACK_ANIMATION:{ |
||||
m.F(A::SWING_OCCURRED)-=fElapsedTime; |
||||
if(m.F(A::SWING_OCCURRED)<=0.f){ |
||||
Arc attackArc{GetAttackArc(m)}; |
||||
if(attackArc.overlaps(game->GetPlayer()->GetPos())){ |
||||
game->GetPlayer()->Knockback(util::pointTo(m.GetPos(),game->GetPlayer()->GetPos())*ConfigFloat("Attack Knockback")); |
||||
game->GetPlayer()->Hurt(m.GetAttack(),m.OnUpperLevel(),m.GetZ()); |
||||
} |
||||
m.F(A::RECOVERY_TIME)=m.GetCurrentAnimation().GetTotalAnimationDuration(); |
||||
m.ANY(A::STORED_ARC)=GetAttackArc(m); |
||||
m.SetStrategyDrawFunction([&storedArc=m.ANY(A::STORED_ARC),attackEffectTime=ConfigFloat("Attack Effect Time")](AiL*game,Monster&monster,const std::string&strategy){ |
||||
const float alphaTimer{float(std::fmod(game->GetRunTime(),2.f))}; |
||||
if(storedArc.has_value()){ |
||||
const uint8_t effectAlpha{util::lerp(uint8_t(0),uint8_t(255),alphaTimer/attackEffectTime)}; |
||||
std::any_cast<Arc>(storedArc).Draw(game,{255,255,255,effectAlpha}); |
||||
} |
||||
}); |
||||
SETPHASE(ATTACK_RECOVERY); |
||||
} |
||||
}break; |
||||
case ATTACK_RECOVERY:{ |
||||
m.F(A::RECOVERY_TIME)-=fElapsedTime; |
||||
if(m.F(A::RECOVERY_TIME)<=0.f){ |
||||
m.PerformIdleAnimation(); |
||||
m.SetStrategyDrawFunction([](AiL*game,Monster&monster,const std::string&strategy){}); |
||||
SETPHASE(SEARCH); |
||||
} |
||||
}break; |
||||
case SUBMERGE:{ |
||||
m.F(A::RECOVERY_TIME)-=fElapsedTime; |
||||
if(m.F(A::RECOVERY_TIME)<=0.f){ |
||||
m.PerformAnimation("RISE"); |
||||
m.F(A::CASTING_TIMER)=m.GetCurrentAnimation().GetTotalAnimationDuration(); |
||||
SETPHASE(RISE_ANIMATION); |
||||
} |
||||
}break; |
||||
} |
||||
} |
@ -0,0 +1,49 @@ |
||||
Giant Octopus |
||||
42000 HP |
||||
Boss boss has a permanent 80% DMG reduction. |
||||
|
||||
Tentacle |
||||
6000 HP |
||||
When a Tentacle dies boss takes 6000 Dmg |
||||
There are 8 Tentacles |
||||
|
||||
Base Damage |
||||
Bullets: 40 |
||||
Big bullet: 90 |
||||
Tentacle: 50 |
||||
|
||||
Attack moves |
||||
- Boss shots 1 bullet every second |
||||
- Every 6. Shot Boss Shots a big bullet that explodes when i gets close to the Player and form a new ring of bullets flying away in a whirl instead of a straight line. (Boss rests for 2 seconds after big bullet) |
||||
- Tentacels do a delayed attack |
||||
- Every Tentacle and the boss get a 10% Attack buff on each Tentacle death |
||||
|
||||
Tentacles: |
||||
- The Tentacles wiggle a bit around between attacks |
||||
- Wiggle phase is 2-4 seconds. |
||||
- Tentacle stopps moving for 1 sec before attacking, already indicating where it will attack. |
||||
- The Tentacle rest on the floor for a short period after an attack ~1 sec (can vary a bit depending how animation looks smoother) |
||||
- The Tentacle attacks with its entire wheight slaming the position where the player was when the movement stopped. |
||||
|
||||
Reference for Tentacle attack https://youtu.be/YtR521QdsNk?si=_TUxuH-3HLnwr_t9&t=475 (Should start at time stamp 07:55 with a bossfight) |
||||
Instead of wiggling around the tentacles supmerge here in between attacks. |
||||
Also instead of this piercing attack i would prefer if its closer to a slam. |
||||
But i really like how the tentacle indicates that its about to attack in a specific direction. |
||||
|
||||
|
||||
Phases |
||||
12k missing Health on boss: |
||||
- boss starts Shooting an Ink Bubble instead of a normal projectile every 15 seconds that explodes and leaves an ink area Lasting for 30 seconds. moving into the ink gives a -10 movespd debuff for 25 seconds. |
||||
- 6 Attacks after first ink attack, every second small bullet has a different Color and has a homing effect. Homing effect is greatly reduced if Player is covered in ink |
||||
|
||||
30k missing Health |
||||
Tentacles get +10% Speed on every animation or attack |
||||
every Projectile get the homing effect |
||||
|
||||
|
||||
|
||||
other stuff |
||||
- On Tentacle death, all Tentacles submerge and recover 1k hp each. after 3 seconds tentacles ascend again one after another 0.25 seconds delay between each Tentacle |
||||
Once the first Tentacle got defeated every 15-25 seconds a Tentacle far away from the Player submerges and appear 2 seconds later again in an area close to the Player, (Only Triggers if there is a free Tentacle spawn close to the Player) |
||||
|
||||
also: technically the limps of an Octopus arent called Tentacles... but whatever, dont feel like changing this in the entire document now. |
@ -0,0 +1,74 @@ |
||||
#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 "MonsterStrategyHelpers.h" |
||||
#include "util.h" |
||||
#include "AdventuresInLestoria.h" |
||||
#include "SoundEffect.h" |
||||
#include "BulletTypes.h" |
||||
|
||||
using A=Attribute; |
||||
|
||||
INCLUDE_game |
||||
|
||||
void Monster::STRATEGY::PARROT(Monster&m,float fElapsedTime,std::string strategy){ |
||||
enum PhaseName{ |
||||
RUN, |
||||
FLY_AWAY, |
||||
}; |
||||
switch(PHASE()){ |
||||
case RUN:{ |
||||
if(!m.attachedTarget.expired()&&m.attachedTarget.lock()->IsAlive()){ |
||||
m.PerformAnimation("FLYING"); |
||||
HAWK(m,fElapsedTime,"Hawk"); |
||||
}else{ |
||||
m.lifetime=10.f; |
||||
SETPHASE(FLY_AWAY); |
||||
m.F(A::PATH_DIR)=1.f; |
||||
if(util::random(1.f)<0.5f)m.F(A::PATH_DIR)=-1.f; |
||||
m.manualIgnoreTerrain=true; |
||||
} |
||||
}break; |
||||
case FLY_AWAY:{ |
||||
if(m.F(A::PATH_DIR)>0.f)m.PerformAnimation("FLYING",Direction::EAST); |
||||
else m.PerformAnimation("FLYING",Direction::WEST); |
||||
m.z+=fElapsedTime*ConfigFloat("Fly Away Z Speed"); |
||||
m.SetVelocity({m.F(A::PATH_DIR)*ConfigFloat("Fly Away Speed"),0.f}); |
||||
}break; |
||||
} |
||||
} |
@ -0,0 +1,118 @@ |
||||
#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 "MonsterStrategyHelpers.h" |
||||
#include "util.h" |
||||
#include "AdventuresInLestoria.h" |
||||
#include "SoundEffect.h" |
||||
#include "BulletTypes.h" |
||||
|
||||
using A=Attribute; |
||||
|
||||
INCLUDE_game |
||||
|
||||
void Monster::STRATEGY::PIRATE_BUCCANEER(Monster&m,float fElapsedTime,std::string strategy){ |
||||
#pragma region Phase, Animation, and Helper function setup |
||||
enum PhaseName{ |
||||
MOVE, |
||||
LOCKON, |
||||
WINDUP, |
||||
FIRE_ANIMATION, |
||||
}; |
||||
#pragma endregion |
||||
|
||||
switch(PHASE()){ |
||||
case MOVE:{ |
||||
m.F(A::ATTACK_COOLDOWN)+=fElapsedTime; |
||||
|
||||
float distToPlayer=m.GetDistanceFrom(game->GetPlayer()->GetPos()); |
||||
|
||||
const bool outsideMaxShootingRange=distToPlayer>=ConfigPixelsArr("Stand Still and Shoot Range",1); |
||||
|
||||
auto PrepareToShoot=[&](){ |
||||
SETPHASE(WINDUP); |
||||
m.F(A::SHOOT_TIMER)=ConfigFloat("Attack Windup Time"); |
||||
m.PerformAnimation("SHOOT",m.GetFacingDirectionToTarget(game->GetPlayer()->GetPos())); |
||||
}; |
||||
|
||||
if(outsideMaxShootingRange){ |
||||
m.target=game->GetPlayer()->GetPos(); |
||||
RUN_TOWARDS(m,fElapsedTime,"Run Towards"); |
||||
}else |
||||
if(m.F(A::ATTACK_COOLDOWN)>=ConfigFloat("Attack Reload Time")){ |
||||
PrepareToShoot(); |
||||
}else |
||||
if(distToPlayer<ConfigPixels("Run Away Range")){ |
||||
m.target=geom2d::line<float>(m.GetPos(),game->GetPlayer()->GetPos()).upoint(-1); |
||||
RUN_TOWARDS(m,fElapsedTime,"Run Towards"); |
||||
}else |
||||
if(m.F(A::ATTACK_COOLDOWN)>=ConfigFloat("Attack Reload Time")/2.f){ //Only the stand still and shoot range remains, which is twice as fast...
|
||||
PrepareToShoot(); |
||||
} |
||||
}break; |
||||
case WINDUP:{ |
||||
m.F(A::SHOOT_TIMER)-=fElapsedTime; |
||||
if(m.F(A::SHOOT_TIMER)<=0){
|
||||
m.F(A::ATTACK_COOLDOWN)=0.f; |
||||
CreateBullet(ChargedArrow)("musket_bullet.png","musket_trail.png",m.GetPos(),util::pointTo(m.GetPos(),m.V(A::LOCKON_POS))*ConfigFloat("Arrow Spd"),ConfigFloat("Arrow Hitbox Radius"),m.GetAttack(),m.OnUpperLevel())EndBullet; |
||||
m.PerformAnimation("SHOOTING",m.GetFacingDirectionToTarget(game->GetPlayer()->GetPos())); |
||||
m.SetStrategyDrawFunction([](AiL*game,Monster&monster,const std::string&strategy){}); |
||||
SETPHASE(FIRE_ANIMATION); |
||||
m.F(A::SHOOT_TIMER)=m.GetCurrentAnimation().GetTotalAnimationDuration(); |
||||
}else |
||||
if(m.F(A::SHOOT_TIMER)>=ConfigFloat("Attack Lockon Time")){ |
||||
m.V(A::LOCKON_POS)=game->GetPlayer()->GetPos(); |
||||
m.PerformAnimation("SHOOT",m.GetFacingDirectionToTarget(game->GetPlayer()->GetPos())); |
||||
const float arrowHitboxRadius{ConfigFloat("Arrow Hitbox Radius")}; |
||||
m.SetStrategyDrawFunction([arrowHitboxRadius](AiL*game,Monster&monster,const std::string&strategy){ |
||||
vf2d midpoint{geom2d::line<float>(monster.GetPos(),monster.V(A::LOCKON_POS)).rpoint(800.f)}; |
||||
float shootingAngle{util::angleTo(monster.GetPos(),monster.V(A::LOCKON_POS))+PI/2}; |
||||
vf2d imgSize{arrowHitboxRadius*2.f,800.f}; |
||||
game->view.DrawPartialRotatedDecal(midpoint,GFX["line_indicator.png"].Decal(),shootingAngle,GFX["line_indicator.png"].Sprite()->Size()/2,{},GFX["line_indicator.png"].Sprite()->Size(),imgSize/GFX["line_indicator.png"].Sprite()->Size()); |
||||
}); |
||||
} |
||||
}break; |
||||
case FIRE_ANIMATION:{ |
||||
m.F(A::SHOOT_TIMER)-=fElapsedTime; |
||||
if(m.F(A::SHOOT_TIMER)<=0.f){ |
||||
m.PerformAnimation("IDLE",m.GetFacingDirectionToTarget(game->GetPlayer()->GetPos())); |
||||
SETPHASE(MOVE); |
||||
} |
||||
}break; |
||||
} |
||||
} |
@ -0,0 +1,183 @@ |
||||
#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 "MonsterStrategyHelpers.h" |
||||
#include "util.h" |
||||
#include "AdventuresInLestoria.h" |
||||
#include "SoundEffect.h" |
||||
#include "BulletTypes.h" |
||||
|
||||
using A=Attribute; |
||||
|
||||
INCLUDE_game |
||||
INCLUDE_ANIMATION_DATA |
||||
|
||||
void Monster::STRATEGY::PIRATE_CAPTAIN(Monster&m,float fElapsedTime,std::string strategy){ |
||||
enum PhaseName{ |
||||
INIT, |
||||
MOVE, |
||||
PREPARE_SHOOT, |
||||
SHOOT_RELOAD, |
||||
DRINK_RUM, |
||||
WINDUP, |
||||
RECOVERY, |
||||
}; |
||||
|
||||
enum AttackType{ |
||||
STAB, |
||||
SLASH |
||||
}; |
||||
|
||||
switch(PHASE()){ |
||||
case INIT:{ |
||||
m.F(A::TARGET_TIMER)=ConfigFloat("Shooting Frequency"); |
||||
m.F(A::PARROT_FLY_TIMER)=ConfigFloat("Parrot Fly Wait Time"); |
||||
m.mounted_animation=Animate2D::Animation<std::string>{}; |
||||
for(bool firstAnimation=true;const std::string&animation:Config("Imposed Monster Animations").GetValues()){ |
||||
m.mounted_animation.value().AddState(animation,ANIMATION_DATA.at(animation)); |
||||
|
||||
if(firstAnimation)m.mounted_animation.value().ChangeState(m.internal_mounted_animState,animation); |
||||
firstAnimation=false; |
||||
} |
||||
m.mountedSprOffset=ConfigVec("Imposed Monster Offset"); |
||||
m.deathData.emplace_back(ConfigString("Spawned Monster"),1U); |
||||
SETPHASE(MOVE); |
||||
}break; |
||||
case MOVE:{ |
||||
if(m.F(A::PARROT_FLY_TIMER)>0.f){ |
||||
m.F(A::PARROT_FLY_TIMER)-=fElapsedTime; |
||||
if(m.F(A::PARROT_FLY_TIMER)<=0.f){ |
||||
m.mounted_animation.reset(); |
||||
Monster&parrot{game->SpawnMonster(m.GetPos(),MONSTER_DATA.at("Parrot"),m.OnUpperLevel())}; |
||||
parrot.attachedTarget=m.GetWeakPointer(); |
||||
} |
||||
} |
||||
m.F(A::TARGET_TIMER)-=fElapsedTime; |
||||
if(m.F(A::TARGET_TIMER)<=0.f){ |
||||
const float diceRoll{util::random(100)}; |
||||
if(diceRoll<=ConfigFloat("Shooting Chance")){ |
||||
const float distToPlayer{util::distance(game->GetPlayer()->GetPos(),m.GetPos())}; |
||||
if(distToPlayer<=ConfigFloat("Shoot Max Range")/100.f*24){ |
||||
m.F(A::SHOOT_TIMER)=ConfigFloat("Shooting Delay"); |
||||
SETPHASE(PREPARE_SHOOT); |
||||
m.PerformAnimation("SHOOT",game->GetPlayer()->GetPos()); |
||||
m.V(A::LOCKON_POS)=game->GetPlayer()->GetPos(); |
||||
} |
||||
} |
||||
m.F(A::TARGET_TIMER)=ConfigFloat("Shooting Frequency"); |
||||
}else |
||||
if(m.GetHealth()<ConfigInt("Rum Drink Threshold")&&m.I(A::RUM_DRINK_COUNT)<ConfigInt("Rum Drink Count")){ |
||||
m.PerformAnimation("DRINK"); |
||||
m.F(A::BREAK_TIME)=m.GetCurrentAnimation().GetTotalAnimationDuration(); |
||||
SETPHASE(DRINK_RUM); |
||||
m.I(A::RUM_DRINK_COUNT)++; |
||||
} |
||||
else{ |
||||
float distToPlayer=m.GetDistanceFrom(game->GetPlayer()->GetPos()); |
||||
if(distToPlayer>ConfigFloat("Attack Spacing")/100.f*24){ |
||||
RUN_TOWARDS(m,fElapsedTime,"Run Towards"); |
||||
}else{ |
||||
SETPHASE(WINDUP); |
||||
m.I(A::ATTACK_TYPE)=util::random()%2; //Choose randomly between stab or slash.
|
||||
switch(m.I(A::ATTACK_TYPE)){ |
||||
case STAB:{ |
||||
m.F(A::CASTING_TIMER)=ConfigFloat("Stab Windup Time"); |
||||
m.PerformAnimation("STAB",m.GetFacingDirectionToTarget(game->GetPlayer()->GetPos())); |
||||
}break; |
||||
case SLASH:{ |
||||
m.F(A::CASTING_TIMER)=ConfigFloat("Slash Windup Time"); |
||||
m.PerformAnimation("SLASH",m.GetFacingDirectionToTarget(game->GetPlayer()->GetPos())); |
||||
}break; |
||||
default:ERR(std::format("WARNING! Invalid Attack type {} provided. THIS SHOULD NOT BE HAPPENING!",m.I(A::ATTACK_TYPE))); |
||||
} |
||||
} |
||||
} |
||||
}break; |
||||
case PREPARE_SHOOT:{ |
||||
m.F(A::SHOOT_TIMER)-=fElapsedTime; |
||||
if(m.F(A::SHOOT_TIMER)<=0.f){ |
||||
CreateBullet(Bullet)(m.GetPos(),util::pointTo(m.GetPos(),m.V(A::LOCKON_POS))*ConfigFloat("Bullet Speed"),ConfigFloat("Bullet Radius"),m.GetAttack(),m.OnUpperLevel(),false,ConfigPixel("Bullet Color"),vf2d{1.f,1.f}*ConfigFloat("Bullet Radius")/3.f)EndBullet; |
||||
m.PerformAnimation("SHOOTING"); |
||||
m.F(A::SHOOT_ANIMATION_TIME)=m.GetCurrentAnimation().GetTotalAnimationDuration(); |
||||
SETPHASE(SHOOT_RELOAD); |
||||
} |
||||
}break; |
||||
case SHOOT_RELOAD:{ |
||||
m.F(A::SHOOT_ANIMATION_TIME)-=fElapsedTime; |
||||
if(m.F(A::SHOOT_ANIMATION_TIME)<=0.f){ |
||||
m.PerformAnimation("IDLE"); |
||||
SETPHASE(MOVE); |
||||
} |
||||
}break; |
||||
case DRINK_RUM:{ |
||||
m.F(A::BREAK_TIME)-=fElapsedTime; |
||||
if(m.F(A::BREAK_TIME)<=0.f){ |
||||
m.Heal(ConfigInt("Rum Health Recovery"),true); |
||||
SETPHASE(MOVE); |
||||
} |
||||
}break; |
||||
case WINDUP:{ |
||||
m.F(A::CASTING_TIMER)-=fElapsedTime; |
||||
if(m.F(A::CASTING_TIMER)<=0){ |
||||
SETPHASE(RECOVERY); |
||||
switch(m.I(A::ATTACK_TYPE)){ |
||||
case STAB:{ |
||||
vf2d stabTarget=game->GetPlayer()->GetPos(); |
||||
m.PerformAnimation("STABBING"); |
||||
CreateBullet(DaggerStab)(m,ConfigString("Dagger Stab Image"),ConfigFloat("Dagger Hit Radius"),m.GetAttack(),ConfigFloat("Dagger Stab Knockback"),m.OnUpperLevel(),m.GetFacingDirection(),ConfigFloat("Dagger Frame Duration"),ConfigFloat("Dagger Stab Distance"), |
||||
DaggerStab::DirectionOffsets{ConfigVec("Dagger Up Offset"),ConfigVec("Dagger Down Offset"),ConfigVec("Dagger Right Offset"),ConfigVec("Dagger Left Offset")})EndBullet; |
||||
}break; |
||||
case SLASH:{ |
||||
vf2d slashTarget=game->GetPlayer()->GetPos(); |
||||
m.PerformAnimation("SLASHING"); |
||||
CreateBullet(DaggerSlash)(m,ConfigString("Dagger Slash Image"),ConfigFloat("Dagger Hit Radius"),m.GetAttack(),ConfigFloat("Dagger Slash Knockback"),m.OnUpperLevel(),m.GetFacingDirection(),ConfigFloat("Dagger Frame Duration"),ConfigFloat("Dagger Slash Distance"))EndBullet; |
||||
}break; |
||||
default:ERR(std::format("WARNING! Invalid Attack type {} provided. THIS SHOULD NOT BE HAPPENING!",m.I(A::ATTACK_TYPE))); |
||||
} |
||||
m.F(A::CASTING_TIMER)=m.GetCurrentAnimation().GetTotalAnimationDuration(); |
||||
m.F(A::RECOVERY_TIME)=ConfigFloat("Attack Recovery Time"); |
||||
} |
||||
}break; |
||||
case RECOVERY:{ |
||||
m.F(A::CASTING_TIMER)-=fElapsedTime; |
||||
m.F(A::RECOVERY_TIME)-=fElapsedTime; |
||||
if(m.F(A::CASTING_TIMER)<=0){m.PerformIdleAnimation(m.GetFacingDirectionToTarget(game->GetPlayer()->GetPos()));} |
||||
if(m.F(A::RECOVERY_TIME)<=0)SETPHASE(MOVE); |
||||
}break; |
||||
} |
||||
} |
@ -0,0 +1,175 @@ |
||||
#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 "MonsterStrategyHelpers.h" |
||||
#include "util.h" |
||||
#include "AdventuresInLestoria.h" |
||||
#include "SoundEffect.h" |
||||
#include "BulletTypes.h" |
||||
|
||||
using A=Attribute; |
||||
|
||||
INCLUDE_game |
||||
|
||||
void Monster::STRATEGY::PIRATE_MARAUDER(Monster&m,float fElapsedTime,std::string strategy){ |
||||
enum PhaseName{ |
||||
INIT, |
||||
MOVE, |
||||
WINDUP, |
||||
RECOVERY, |
||||
LEAP, |
||||
PREPARE_WHIRLWIND, |
||||
WHIRLWIND, |
||||
}; |
||||
|
||||
switch(PHASE()){ |
||||
case INIT:{ |
||||
m.F(A::CHASE_TIMER)=ConfigFloat("Ability Choose Timer"); |
||||
SETPHASE(MOVE); |
||||
}break; |
||||
case MOVE:{ |
||||
float distToPlayer=m.GetDistanceFrom(game->GetPlayer()->GetPos()); |
||||
|
||||
m.F(A::CHASE_TIMER)-=fElapsedTime; |
||||
if(m.F(A::CHASE_TIMER)<=0.f){ |
||||
m.I(A::ABILITY_COUNT)++; |
||||
m.F(A::CHASE_TIMER)=ConfigFloat("Ability Choose Timer"); |
||||
} |
||||
|
||||
if(m.I(A::ABILITY_COUNT)>0){ |
||||
float roll{util::random_range(0.f,100.f)}; |
||||
float distanceToPlayer{util::distance(m.GetPos(),game->GetPlayer()->GetPos())}; |
||||
std::pair<float,float>jumpAttackRollRange{0.f,ConfigFloat("Jump Attack Chance")}; |
||||
std::pair<float,float>whirlwindAttackRollRange{jumpAttackRollRange.second,jumpAttackRollRange.second+ConfigFloat("Whirlwind Attack Chance")}; |
||||
|
||||
if(roll<jumpAttackRollRange.second&&distanceToPlayer>=ConfigFloatArr("Jump Attack Ranges",0)/100.f*24.f&&distanceToPlayer<=ConfigFloatArr("Jump Attack Ranges",1)/100.f*24.f){ |
||||
SETPHASE(LEAP); |
||||
m.V(A::JUMP_TARGET_POS)=game->GetPlayer()->GetPos(); |
||||
m.I(A::ABILITY_COUNT)--; |
||||
const float impactArea{ConfigFloat("Jump Attack Impact Area")}; |
||||
m.SetStrategyDrawFunction([impactArea](AiL*game,Monster&monster,const std::string&strategy){ |
||||
game->view.DrawRotatedDecal(monster.V(A::JUMP_TARGET_POS),GFX["range_indicator.png"].Decal(),0.f,GFX["range_indicator.png"].Sprite()->Size()/2.f,vf2d{1,1}*(impactArea/100.f),{255,0,0,96}); |
||||
}); |
||||
m.F(A::JUMP_MOVE_TO_TARGET_TIMER)=0.f; |
||||
m.V(A::PREV_POS)=m.GetPos(); |
||||
m.PerformAnimation("LEAPING",m.V(A::JUMP_TARGET_POS)); |
||||
break; |
||||
}else |
||||
if(roll>=whirlwindAttackRollRange.first&&roll<whirlwindAttackRollRange.second |
||||
&&distanceToPlayer>=ConfigFloatArr("Whirlwind Attack Ranges",0)/100.f*24.f&&distanceToPlayer<=ConfigFloatArr("Whirlwind Attack Ranges",1)/100.f*24.f){ |
||||
SETPHASE(PREPARE_WHIRLWIND); |
||||
m.I(A::ABILITY_COUNT)--; |
||||
vf2d aimingTarget{game->GetPlayer()->GetPos()}; |
||||
if(aimingTarget==m.GetPos()){ //Handle edge case.
|
||||
aimingTarget=m.GetPos()+vf2d{1.f,util::random(2*PI)}.cart(); |
||||
} |
||||
m.V(A::PATH_DIR)=util::pointTo(m.GetPos(),aimingTarget); |
||||
m.PerformAnimation("SPIN",m.V(A::LOCKON_POS)); |
||||
m.F(A::CASTING_TIMER)=ConfigFloat("Whirlwind Chargeup Time"); |
||||
m.AddBuff(BuffType::SPEEDBOOST,ConfigFloat("Whirlwind Spin Time"),ConfigFloat("Whirlwind Bonus Movespd")/100.f); |
||||
break; |
||||
} |
||||
} |
||||
NormalBehavior: |
||||
if(distToPlayer>ConfigFloat("Attack Spacing")/100.f*24){ |
||||
RUN_TOWARDS(m,fElapsedTime,"Run Towards"); |
||||
}else{ |
||||
SETPHASE(WINDUP); |
||||
m.F(A::CASTING_TIMER)=ConfigFloat("Slash Windup Time"); |
||||
m.PerformAnimation("SLASH",m.GetFacingDirectionToTarget(game->GetPlayer()->GetPos())); |
||||
} |
||||
}break; |
||||
case WINDUP:{ |
||||
m.F(A::CASTING_TIMER)-=fElapsedTime; |
||||
if(m.F(A::CASTING_TIMER)<=0){ |
||||
SETPHASE(RECOVERY); |
||||
vf2d slashTarget=game->GetPlayer()->GetPos(); |
||||
m.PerformAnimation("SLASHING",m.GetFacingDirectionToTarget(game->GetPlayer()->GetPos())); |
||||
CreateBullet(DaggerSlash)(m,ConfigString("Dagger Slash Image"),ConfigFloat("Dagger Hit Radius"),m.GetAttack(),ConfigFloat("Dagger Slash Knockback"),m.OnUpperLevel(),m.GetFacingDirectionToTarget(slashTarget),ConfigFloat("Dagger Frame Duration"),ConfigFloat("Dagger Slash Distance"))EndBullet; |
||||
m.F(A::CASTING_TIMER)=m.GetCurrentAnimation().GetTotalAnimationDuration(); |
||||
m.F(A::RECOVERY_TIME)=ConfigFloat("Attack Recovery Time"); |
||||
} |
||||
}break; |
||||
case RECOVERY:{ |
||||
m.F(A::CASTING_TIMER)-=fElapsedTime; |
||||
m.F(A::RECOVERY_TIME)-=fElapsedTime; |
||||
if(m.F(A::CASTING_TIMER)<=0){m.PerformIdleAnimation(m.GetFacingDirectionToTarget(game->GetPlayer()->GetPos()));} |
||||
if(m.F(A::RECOVERY_TIME)<=0)SETPHASE(MOVE); |
||||
}break; |
||||
case LEAP:{ |
||||
m.F(A::JUMP_MOVE_TO_TARGET_TIMER)+=fElapsedTime; |
||||
const float halfJumpTime{ConfigFloat("Jump Attack Duration")/2.f}; |
||||
if(m.F(A::JUMP_MOVE_TO_TARGET_TIMER)<halfJumpTime)m.SetZ(util::smoothstep(0,ConfigFloat("Jump Attack Height"),m.F(A::JUMP_MOVE_TO_TARGET_TIMER)/halfJumpTime)); |
||||
else m.SetZ(util::smoothstep(ConfigFloat("Jump Attack Height"),0,(m.F(A::JUMP_MOVE_TO_TARGET_TIMER)-halfJumpTime)/halfJumpTime)); |
||||
m.SetPos(m.V(A::PREV_POS).lerp(m.V(A::JUMP_TARGET_POS),m.F(A::JUMP_MOVE_TO_TARGET_TIMER)/ConfigFloat("Jump Attack Duration"))); |
||||
if(m.F(A::JUMP_MOVE_TO_TARGET_TIMER)>=ConfigFloat("Jump Attack Duration")){ |
||||
SoundEffect::PlaySFX("Leap Land",m.GetPos()); |
||||
game->Hurt(m.GetPos(),ConfigFloat("Jump Attack Impact Area")/100.f*24.f,m.GetAttack(),m.OnUpperLevel(),m.GetZ(),HurtType::PLAYER); |
||||
game->ProximityKnockback(m.GetPos(),ConfigFloat("Jump Attack Impact Area")/100.f*24.f,ConfigFloat("Jump Attack Knockback Amount"),HurtType::MONSTER|HurtType::PLAYER); |
||||
m.SetZ(0.f); |
||||
m.SetPos(m.V(A::JUMP_TARGET_POS)); |
||||
SETPHASE(MOVE); |
||||
m.PerformIdleAnimation(); |
||||
m.SetStrategyDrawFunction([](AiL*game,Monster&monster,const std::string&strategy){}); |
||||
} |
||||
}break; |
||||
case PREPARE_WHIRLWIND:{ |
||||
m.F(A::CASTING_TIMER)-=fElapsedTime; |
||||
if(m.F(A::CASTING_TIMER)<=0.f){ |
||||
SETPHASE(WHIRLWIND); |
||||
m.F(A::CHASE_TIMER)=0.f; |
||||
m.PerformAnimation("SPINNING"); |
||||
} |
||||
}break; |
||||
case WHIRLWIND:{ |
||||
m.F(A::CHASE_TIMER)+=fElapsedTime; |
||||
if(m.F(A::CHASE_TIMER)>=ConfigFloat("Whirlwind Spin Time")){ |
||||
SETPHASE(MOVE); |
||||
m.PerformIdleAnimation(); |
||||
} |
||||
m.MoveForward(m.V(A::PATH_DIR),fElapsedTime); |
||||
const HurtList hurtTargets{game->Hurt(m.GetPos(),ConfigFloat("Whirlwind Radius")/100.f*24.f,m.GetAttack(),m.OnUpperLevel(),m.GetZ(),HurtType::PLAYER)}; |
||||
for(auto&[target,isHurt]:hurtTargets){ |
||||
if(std::holds_alternative<Player*>(target)){ |
||||
(std::get<Player*>(target))->ApplyIframes(0.5f); |
||||
}else ERR("WARNING! Somehow ended up with a non-player entity for whirlwind damage check! THIS SHOULD NOT BE HAPPENING!") |
||||
} |
||||
game->ProximityKnockback(m.GetPos(),ConfigFloat("Whirlwind Radius")/100.f*24.f,ConfigFloat("Whirlwind Knockback Amount"),HurtType::MONSTER|HurtType::PLAYER); |
||||
}break; |
||||
} |
||||
} |
@ -0,0 +1,139 @@ |
||||
#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 "MonsterStrategyHelpers.h" |
||||
#include "util.h" |
||||
#include "AdventuresInLestoria.h" |
||||
#include "SoundEffect.h" |
||||
#include "BulletTypes.h" |
||||
|
||||
using A=Attribute; |
||||
|
||||
INCLUDE_game |
||||
|
||||
void Monster::STRATEGY::SANDWORM(Monster&m,float fElapsedTime,std::string strategy){ |
||||
enum PhaseName{ |
||||
INITIALIZE, |
||||
UNDERGROUND, |
||||
SURFACING, |
||||
ATTACK, |
||||
SHOOTING, |
||||
BURROWING, |
||||
}; |
||||
|
||||
m.F(A::ATTACK_COOLDOWN)-=fElapsedTime; |
||||
m.F(A::SUCTION_TIMER)-=fElapsedTime; |
||||
const float distToPlayer{util::distance(game->GetPlayer()->GetPos(),m.GetPos())}; |
||||
if(m.F(A::SUCTION_TIMER)>0.f&&distToPlayer<=ConfigPixels("Suction Radius")){ |
||||
game->GetPlayer()->AddVelocity(util::pointTo(game->GetPlayer()->GetPos(),m.GetPos())*100.f*ConfigFloat("Suction Pull Amount")/100.f); |
||||
} |
||||
|
||||
const auto AcquireNewUndergroundTarget=[&](){ |
||||
const float randomRange=util::random_range(0,ConfigPixels("Burrow Target Range")); |
||||
m.target=game->GetPlayer()->GetPos()+vf2d{randomRange,util::random(2*PI)}.cart(); |
||||
}; |
||||
|
||||
switch(PHASE()){ |
||||
case INITIALIZE:{ |
||||
SETPHASE(UNDERGROUND); |
||||
AcquireNewUndergroundTarget(); |
||||
}break; |
||||
case UNDERGROUND:{ |
||||
m.SetCollisionRadius(0.f); |
||||
RUN_TOWARDS(m,fElapsedTime,"Run Towards"); |
||||
m.PerformAnimation("SWIM",m.GetFacingDirection()); |
||||
if(m.ReachedTargetPos()){ |
||||
m.PerformAnimation("EMERGE",game->GetPlayer()->GetPos()); |
||||
m.F(A::RECOVERY_TIME)=m.GetCurrentAnimation().GetTotalAnimationDuration(); |
||||
game->AddEffect(std::make_unique<Effect>(m.GetPos(),ConfigInt("Suction Duration"),"sand_suction.png",m.OnUpperLevel(),0.25f,0.25f,ConfigFloat("Suction Animation Size")/300.f*vf2d{1.f,1.f},vf2d{},WHITE,util::random(),-PI/8),true); |
||||
SETPHASE(SURFACING); |
||||
m.F(A::SUCTION_TIMER)=ConfigFloat("Suction Duration")+0.25f; |
||||
} |
||||
}break; |
||||
case SURFACING:{ |
||||
m.F(A::RECOVERY_TIME)-=fElapsedTime; |
||||
if(m.F(A::RECOVERY_TIME)<=0.f){ |
||||
SETPHASE(ATTACK); |
||||
m.PerformAnimation("IDLE",game->GetPlayer()->GetPos()); |
||||
m.SetCollisionRadius(m.GetOriginalCollisionRadius()); |
||||
m.I(A::ATTACK_COUNT)=ConfigInt("Max Attack Count"); |
||||
} |
||||
}break; |
||||
case ATTACK:{ |
||||
if(m.I(A::ATTACK_COUNT)<=0||distToPlayer>=ConfigPixels("Max Attack Range")){ |
||||
m.SetCollisionRadius(0.f); |
||||
m.PerformAnimation("BURROW"); |
||||
m.F(A::CASTING_TIMER)=m.GetCurrentAnimation().GetTotalAnimationDuration(); |
||||
SETPHASE(BURROWING); |
||||
break; |
||||
} |
||||
if(m.F(A::ATTACK_COOLDOWN)<=0.f){ |
||||
m.PerformAnimation("SAND ATTACK",game->GetPlayer()->GetPos()); |
||||
m.F(A::CASTING_TIMER)=ConfigFloat("Shoot Delay"); |
||||
m.F(A::SHOOT_ANIMATION_TIME)=m.GetCurrentAnimation().GetTotalAnimationDuration(); |
||||
m.B(A::BULLET_HAS_BEEN_SHOT)=false; |
||||
SETPHASE(SHOOTING); |
||||
} |
||||
}break; |
||||
case SHOOTING:{ |
||||
const auto ShootBullet=[&](){ |
||||
m.B(A::BULLET_HAS_BEEN_SHOT)=true; |
||||
m.I(A::ATTACK_COUNT)--; |
||||
CreateBullet(Bullet)(m.GetPos(),vf2d{ConfigPixels("Bullet Speed"),util::angleTo(m.GetPos(),game->GetPlayer()->GetPos())}.cart(),ConfigFloat("Bullet Radius"),m.GetAttack(),m.OnUpperLevel(),false,ConfigPixel("Bullet Color"),ConfigFloat("Bullet Radius")*vf2d{1.f,1.f}/2.f)EndBullet; |
||||
}; |
||||
|
||||
m.F(A::CASTING_TIMER)-=fElapsedTime; |
||||
m.F(A::SHOOT_ANIMATION_TIME)-=fElapsedTime; |
||||
if(m.F(A::CASTING_TIMER)<=0.f&&!m.B(A::BULLET_HAS_BEEN_SHOT)){ |
||||
ShootBullet(); |
||||
} |
||||
if(m.F(A::SHOOT_ANIMATION_TIME)<=0.f){ |
||||
if(!m.B(A::BULLET_HAS_BEEN_SHOT))ShootBullet(); |
||||
m.PerformAnimation("IDLE",game->GetPlayer()->GetPos()); |
||||
SETPHASE(ATTACK); |
||||
} |
||||
}break; |
||||
case BURROWING:{ |
||||
m.F(A::CASTING_TIMER)-=fElapsedTime; |
||||
if(m.F(A::CASTING_TIMER)<=0.f){ |
||||
AcquireNewUndergroundTarget(); |
||||
SETPHASE(UNDERGROUND); |
||||
} |
||||
}break; |
||||
} |
||||
} |
@ -0,0 +1,86 @@ |
||||
#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 "MonsterStrategyHelpers.h" |
||||
#include "util.h" |
||||
#include "AdventuresInLestoria.h" |
||||
#include "SoundEffect.h" |
||||
#include "BulletTypes.h" |
||||
|
||||
using A=Attribute; |
||||
|
||||
INCLUDE_game |
||||
|
||||
void Monster::STRATEGY::SEAGULL(Monster&m,float fElapsedTime,std::string strategy){ |
||||
enum PhaseName{ |
||||
CHILLING, |
||||
STARTLED, |
||||
FLY_AWAY, |
||||
DISABLED, |
||||
}; |
||||
|
||||
switch(PHASE()){ |
||||
case CHILLING:{ |
||||
m.PerformAnimation("IDLE",game->GetPlayer()->GetPos()); |
||||
float distToPlayer{util::distance(game->GetPlayer()->GetPos(),m.GetPos())}; |
||||
if(distToPlayer<=ConfigFloat("Startled Range")/100.f*24){ |
||||
SETPHASE(STARTLED); |
||||
m.F(A::CASTING_TIMER)=ConfigFloat("Takeoff Time"); |
||||
m.V(A::PREV_POS)=m.GetPos(); |
||||
} |
||||
}break; |
||||
case STARTLED:{ |
||||
m.PerformAnimation("FLY",m.GetPos()+util::pointTo(game->GetPlayer()->GetPos(),m.GetPos())); |
||||
m.F(A::CASTING_TIMER)-=fElapsedTime; |
||||
if(m.F(A::CASTING_TIMER)<=0.f)SETPHASE(FLY_AWAY); |
||||
}break; |
||||
case FLY_AWAY:{ |
||||
vf2d moveVec{m.GetPos()-game->GetPlayer()->GetPos()}; |
||||
m.PerformAnimation("FLY",m.GetPos()+util::pointTo(game->GetPlayer()->GetPos(),m.GetPos())); |
||||
m.MoveForward(moveVec,fElapsedTime); |
||||
float distTraveled{util::distance(m.V(A::PREV_POS),m.GetPos())}; |
||||
if(distTraveled>=ConfigFloat("Despawn Range")/100.f*24){ |
||||
m.lifetime=1.f; |
||||
SETPHASE(DISABLED); |
||||
} |
||||
}break; |
||||
case DISABLED:{ |
||||
//NO-OP
|
||||
}break; |
||||
} |
||||
} |
@ -0,0 +1,95 @@ |
||||
#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 "BulletTypes.h" |
||||
#include "AdventuresInLestoria.h" |
||||
#include <ranges> |
||||
#include "util.h" |
||||
#include "SoundEffect.h" |
||||
|
||||
INCLUDE_game |
||||
|
||||
ThrownProjectile::ThrownProjectile(vf2d pos,vf2d targetPos,const std::string&img,float explodeRadius,float z,float totalFallTime,float totalRiseZAmt,int damage,bool upperLevel,bool hitsMultiple,float lifetime,bool friendly,Pixel col,vf2d scale,float image_angle,const std::optional<Effect>explodeEffect,const std::optional<std::string>explodeSoundEffect,const std::optional<LingeringEffect>lingeringEffect) |
||||
:Bullet(pos,util::pointTo(pos,targetPos)*util::distance(pos,targetPos)/totalFallTime,0.f,damage,img,upperLevel,hitsMultiple,lifetime,false,friendly,col,scale,image_angle),initialZ(z),explodeRadius(explodeRadius),totalRiseZAmt(totalRiseZAmt),totalFallTime(totalFallTime),startingPos(pos),targetPos(targetPos),originalRisingTime(totalFallTime*0.25f),risingTime(originalRisingTime),originalFallingTime(totalFallTime*0.75f),fallingTime(originalFallingTime),explodeEffect(explodeEffect),img(img),explodeSoundEffect(explodeSoundEffect),lingeringEffect(lingeringEffect){ |
||||
this->z=z; |
||||
} |
||||
|
||||
void ThrownProjectile::OnGroundLand(){ |
||||
const HurtList hurtList{game->Hurt(pos,explodeRadius,damage,OnUpperLevel(),z,HurtType::MONSTER,HurtFlag::PLAYER_ABILITY)}; |
||||
if(explodeEffect){ |
||||
Effect&explosionEffect{game->AddEffect(std::make_unique<Effect>(explodeEffect.value()))}; |
||||
explosionEffect.pos+=pos; |
||||
} |
||||
if(explodeSoundEffect)SoundEffect::PlaySFX(explodeSoundEffect.value(),pos); |
||||
if(lingeringEffect){ |
||||
LingeringEffect&lingerEffect{dynamic_cast<LingeringEffect&>(game->AddEffect(std::make_unique<LingeringEffect>(lingeringEffect.value())))}; |
||||
lingerEffect.posOscillator.val1+=pos; |
||||
lingerEffect.posOscillator.val2+=pos; |
||||
lingerEffect.pos+=pos; |
||||
} |
||||
|
||||
vel={}; |
||||
fadeOutTime=0.25f; |
||||
Deactivate(); |
||||
} |
||||
void ThrownProjectile::_OnGroundLand(){ |
||||
z=0.f; |
||||
OnGroundLand(); |
||||
} |
||||
|
||||
void ThrownProjectile::Update(float fElapsedTime){ |
||||
if(IsDeactivated())return; |
||||
image_angle+=0.5*PI*fElapsedTime; |
||||
|
||||
const bool Landed{fallingTime<=0.f}; |
||||
if(Landed){ |
||||
_OnGroundLand(); |
||||
}else{ |
||||
if(risingTime>0.f){ |
||||
risingTime-=fElapsedTime; |
||||
z=util::lerp(initialZ,initialZ+totalRiseZAmt,1-(risingTime/originalRisingTime)); |
||||
}else{ |
||||
fallingTime-=fElapsedTime; |
||||
z=util::lerp(initialZ+totalRiseZAmt,0.f,1-(fallingTime/originalFallingTime)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
void ThrownProjectile::ModifyOutgoingDamageData(HurtDamageInfo&data){ |
||||
if(friendly)data.hurtFlags|=HurtFlag::PLAYER_ABILITY; |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue