Setup framework for the goblin boar rider.
This commit is contained in:
parent
3051422383
commit
c83f84f29c
@ -712,6 +712,10 @@
|
||||
</SubType>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GameState.cpp" />
|
||||
<ClCompile Include="MountMonster.cpp">
|
||||
<SubType>
|
||||
</SubType>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Goblin_Bow.cpp">
|
||||
<SubType>
|
||||
</SubType>
|
||||
|
@ -249,6 +249,27 @@ void sig::Animation::InitializeAnimations(){
|
||||
CreateStillAnimation("laser.png",{5,1});
|
||||
CreateStillAnimation("range_indicator.png",{24,24});
|
||||
|
||||
Animate2D::FrameSequence goblin_bow_mount_n,goblin_bow_mount_e,goblin_bow_mount_s,goblin_bow_mount_w;
|
||||
Animate2D::FrameSequence goblin_bow_attack_n,goblin_bow_attack_e,goblin_bow_attack_s,goblin_bow_attack_w;
|
||||
//Idle sequences for the mounted boar bow goblin.
|
||||
for(int animationIndex=0;animationIndex<4;animationIndex++){
|
||||
Animate2D::FrameSequence mountAnimation;
|
||||
for(int i=0;i<2;i++){
|
||||
mountAnimation.AddFrame(Animate2D::Frame{&GFX["monsters/commercial_assets/Goblin (Bow)_foreground.png"],{{i*32,animationIndex*32},{32,32}}});
|
||||
}
|
||||
ANIMATION_DATA[std::format("GOBLIN_BOW_MOUNTED_{}",animationIndex)]=mountAnimation;
|
||||
animationIndex++;
|
||||
}
|
||||
//Shooting sequences for the mounted boar bow goblin.
|
||||
for(int animationIndex=0;animationIndex<4;animationIndex++){
|
||||
Animate2D::FrameSequence mountShootAnimation;
|
||||
for(int i=0;i<4;i++){
|
||||
mountShootAnimation.AddFrame(Animate2D::Frame{&GFX["monsters/commercial_assets/Goblin (Bow)_foreground.png"],{{i*32,index*32+4*32},{32,32}}});
|
||||
}
|
||||
ANIMATION_DATA[std::format("GOBLIN_BOW_ATTACK_{}",animationIndex)]=mountShootAnimation;
|
||||
animationIndex++;
|
||||
}
|
||||
|
||||
for(auto&dat:GFX){
|
||||
std::string imgFile=dat.first;
|
||||
if(!ANIMATION_DATA.count(imgFile)){
|
||||
|
@ -379,6 +379,7 @@ void Monster::UpdateFacingDirection(vf2d facingTargetPoint){
|
||||
}
|
||||
}
|
||||
animation.ModifyDisplaySprite(internal_animState,std::format("{}_{}",animation.currentStateName.substr(0,animation.currentStateName.length()-2),int(facingDirection)));
|
||||
if(HasMountedMonster())mounted_animation.value().ModifyDisplaySprite(internal_mounted_animState.value(),std::format("{}_{}",mounted_animation.value().currentStateName.substr(0,mounted_animation.value().currentStateName.length()-2),int(facingDirection)));
|
||||
}else{
|
||||
if(diff.x>0){
|
||||
facingDirection=Direction::EAST;
|
||||
@ -398,6 +399,7 @@ void Monster::Draw()const{
|
||||
if(overlaySprite.length()!=0){
|
||||
game->view.DrawPartialRotatedDecal(GetPos()-vf2d{0,GetZ()},GFX[overlaySprite].Decal(),spriteRot,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,vf2d(GetSizeMult()*(!HasFourWaySprites()&&GetFacingDirection()==Direction::WEST?-1:1),GetSizeMult()),{blendCol.r,blendCol.g,blendCol.b,overlaySpriteTransparency});
|
||||
}
|
||||
if(HasMountedMonster())game->view.DrawPartialRotatedDecal(GetPos()-vf2d{0,GetZ()},GetMountedFrame().GetSourceImage()->Decal(),spriteRot,GetMountedFrame().GetSourceRect().size/2,GetMountedFrame().GetSourceRect().pos,GetMountedFrame().GetSourceRect().size,vf2d(GetSizeMult()*(!HasFourWaySprites()&&GetFacingDirection()==Direction::EAST?-1:1),GetSizeMult()),blendCol);
|
||||
|
||||
std::vector<Buff>shieldBuffs=GetBuffs(BARRIER_DAMAGE_REDUCTION);
|
||||
if(shieldBuffs.size()>0){
|
||||
@ -942,4 +944,14 @@ const Direction Monster::GetFacingDirectionToTarget(vf2d target)const{
|
||||
|
||||
const bool Monster::HasFourWaySprites()const{
|
||||
return MONSTER_DATA.at(name).HasFourWaySprites();
|
||||
}
|
||||
|
||||
const bool Monster::HasMountedMonster()const{
|
||||
if(internal_mounted_animState.has_value()^mounted_animation.has_value())ERR("WARNING! The internal mounted animation state and the mounted animation variables are not matching! They should both either be on or both be off! THIS SHOULD NOT BE HAPPENING!");
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::optional<const Animate2D::Frame&>Monster::GetMountedFrame()const{
|
||||
if(!HasMountedMonster())return {};
|
||||
else return mounted_animation.value().GetFrame(internal_mounted_animState.value());
|
||||
}
|
@ -50,6 +50,8 @@ All rights reserved.
|
||||
#include "Direction.h"
|
||||
|
||||
INCLUDE_ITEM_DATA
|
||||
INCLUDE_MONSTER_DATA
|
||||
INCLUDE_game
|
||||
|
||||
struct DamageNumber;
|
||||
class AiL;
|
||||
@ -58,6 +60,22 @@ enum class Attribute;
|
||||
|
||||
class GameEvent;
|
||||
|
||||
class DeathSpawnInfo{
|
||||
std::string monsterSpawnName;
|
||||
uint8_t spawnAmt;
|
||||
vf2d spawnLocOffset;
|
||||
public:
|
||||
DeathSpawnInfo(const std::string_view monsterName,const uint8_t spawnAmt,const vf2d spawnOffset={})
|
||||
:monsterSpawnName(monsterName),spawnAmt(spawnAmt),spawnLocOffset(spawnOffset){
|
||||
if(!MONSTER_DATA.count(std::string(monsterName)))ERR(std::format("WARNING! Monster {} specified in DeathSpawnInfo does not exist! Please provide a proper monster name.",monsterName));
|
||||
}
|
||||
void Spawn(const vf2d monsterDeathPos,const bool onUpperLevel){
|
||||
for(uint8_t i=0;i<spawnAmt;i++){
|
||||
game->SpawnMonster(monsterDeathPos+spawnLocOffset,MONSTER_DATA.at(monsterSpawnName),onUpperLevel);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class Monster:IAttributable{
|
||||
friend struct STRATEGY;
|
||||
friend class AiL;
|
||||
@ -74,6 +92,7 @@ public:
|
||||
//Obtains the size multiplier (from 0.f-1.f).
|
||||
float GetSizeMult()const;
|
||||
Animate2D::Frame GetFrame()const;
|
||||
const std::optional<const Animate2D::Frame&>GetMountedFrame()const;
|
||||
bool Update(float fElapsedTime);
|
||||
//Returns true when damage is actually dealt. Provide whether or not the attack is on the upper level or not. Monsters must be on the same level to get hit by it. (there is a death check and level check here.)
|
||||
//If you need to hurt multiple enemies try AiL::HurtEnemies()
|
||||
@ -148,6 +167,7 @@ public:
|
||||
const float GetDistanceFrom(vf2d target)const;
|
||||
const Direction GetFacingDirectionToTarget(vf2d target)const;
|
||||
const bool HasFourWaySprites()const;
|
||||
const bool HasMountedMonster()const;
|
||||
private:
|
||||
std::string name;
|
||||
vf2d pos;
|
||||
@ -170,6 +190,8 @@ private:
|
||||
uint8_t overlaySpriteTransparency=0U;
|
||||
Animate2D::Animation<std::string>animation;
|
||||
Animate2D::AnimationState internal_animState;
|
||||
std::optional<Animate2D::Animation<std::string>>mounted_animation;
|
||||
std::optional<Animate2D::AnimationState>internal_mounted_animState;
|
||||
float randomFrameOffset=0.f;
|
||||
float deathTimer=0.f;
|
||||
float monsterHurtSoundCooldown=0.f;
|
||||
@ -213,7 +235,7 @@ private:
|
||||
std::map<ItemInfo*,uint16_t>SpawnDrops();
|
||||
float prevFacingDirectionAngle=0.f; //Keeps track of the angle of the previous target to ensure four-way sprite facing changes don't happen too early or spastically.
|
||||
float lastFacingDirectionChange=0.f; //How much time has passed since the last facing direction change. Used to ensure another facing direction change doesn't happen too quickly. Probably allowing one every quarter second is good enough.
|
||||
|
||||
std::vector<DeathSpawnInfo>deathData; //Data that contains further actions and information when this monster dies. Mostly used to spawn sub-monsters from a defeated monster.
|
||||
private:
|
||||
struct STRATEGY{
|
||||
static int _GetInt(Monster&m,std::string param,std::string strategy,int index=0);
|
||||
@ -238,6 +260,7 @@ private:
|
||||
static void BOAR(Monster&m,float fElapsedTime,std::string strategy);
|
||||
static void GOBLIN_DAGGER(Monster&m,float fElapsedTime,std::string strategy);
|
||||
static void GOBLIN_BOW(Monster&m,float fElapsedTime,std::string strategy);
|
||||
static void GOBLIN_BOAR_RIDER(Monster&m,float fElapsedTime,std::string strategy);
|
||||
};
|
||||
bool bumpedIntoTerrain=false; //Gets set to true before a strategy executes if the monster runs into some terrain on this frame.
|
||||
bool attackedByPlayer=false; //Gets set to true before a strategy executes if the monster has been attacked by the player.
|
||||
|
@ -112,4 +112,5 @@ enum class Attribute{
|
||||
RANDOM_DIRECTION,
|
||||
RANDOM_RANGE,
|
||||
PERCEPTION_LEVEL,
|
||||
INITIALIZED_MOUNTED_MONSTER,
|
||||
};
|
57
Adventures in Lestoria/MountMonster.cpp
Normal file
57
Adventures in Lestoria/MountMonster.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
#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 "DEFINES.h"
|
||||
#include "Monster.h"
|
||||
#include "MonsterStrategyHelpers.h"
|
||||
|
||||
INCLUDE_ANIMATION_DATA
|
||||
|
||||
using A=Attribute;
|
||||
|
||||
void Monster::STRATEGY::GOBLIN_BOAR_RIDER(Monster&m,float fElapsedTime,std::string strategy){
|
||||
//We have access to GOBLIN_BOW_MOUNTED_X and GOBLIN_BOW_ATTACK_X
|
||||
if(!m.B(A::INITIALIZED_MOUNTED_MONSTER)){
|
||||
m.B(A::INITIALIZED_MOUNTED_MONSTER)=true;
|
||||
m.internal_mounted_animState=Animate2D::AnimationState{};
|
||||
m.mounted_animation=Animate2D::Animation<std::string>{};
|
||||
for(const std::string&animation:Config("Imposed Monster Animations").GetValues()){
|
||||
m.mounted_animation.value().AddState(animation,ANIMATION_DATA.at(animation));
|
||||
}
|
||||
}
|
||||
}
|
@ -56,6 +56,7 @@ void Monster::InitializeStrategies(){
|
||||
STRATEGY_DATA.insert("Boar",Monster::STRATEGY::BOAR);
|
||||
STRATEGY_DATA.insert("Goblin Dagger",Monster::STRATEGY::GOBLIN_DAGGER);
|
||||
STRATEGY_DATA.insert("Goblin Bow",Monster::STRATEGY::GOBLIN_BOW);
|
||||
STRATEGY_DATA.insert("Goblin Boar Rider",Monster::STRATEGY::GOBLIN_BOAR_RIDER);
|
||||
|
||||
STRATEGY_DATA.SetInitialized();
|
||||
}
|
||||
|
@ -613,4 +613,12 @@ MonsterStrategy
|
||||
Perception Level Increase = 2.5
|
||||
Maximum Perception Level = 45
|
||||
}
|
||||
Goblin Boar Rider
|
||||
{
|
||||
# Which monster spawns on death of the boar.
|
||||
Spawned Monster = Goblin (Bow)
|
||||
Imposed Monster Spritesheet = Goblin (Bow)_foreground.png
|
||||
Imposed Monster Offset = 0,-10
|
||||
Imposed Monster Animations = GOBLIN_BOW_MOUNTED_0,GOBLIN_BOW_MOUNTED_1,GOBLIN_BOW_MOUNTED_2,GOBLIN_BOW_MOUNTED_3,GOBLIN_BOW_ATTACK_0,GOBLIN_BOW_ATTACK_1,GOBLIN_BOW_ATTACK_2,GOBLIN_BOW_ATTACK_3,
|
||||
}
|
||||
}
|
@ -89,6 +89,7 @@ Images
|
||||
GFX_DaggerStab = dagger_stab.png
|
||||
GFX_GoblinSwordSlash = goblin_sword_slash.png
|
||||
GFX_GoblinArrow = goblin_arrow.png
|
||||
GFX_GoblinBowForeground = monsters/commercial_assets/Goblin (Bow)_foreground.png
|
||||
|
||||
# Ability Icons
|
||||
GFX_Warrior_BattleCry_Icon = Ability Icons/battlecry.png
|
||||
|
Loading…
x
Reference in New Issue
Block a user