Attack recovery time on frogs were being ignored. Made move speed stats implementations consistent across both monsters and players. Added shooting sound effects. Begin wolf behavior implementation.

pull/30/head
sigonasr2 11 months ago
parent e8d2ec9e9d
commit acaf1bc3bf
  1. 1
      Adventures in Lestoria/Adventures in Lestoria.vcxproj
  2. 3
      Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters
  3. 2
      Adventures in Lestoria/Buff.h
  4. 8
      Adventures in Lestoria/Frog.cpp
  5. 12
      Adventures in Lestoria/Monster.cpp
  6. 1
      Adventures in Lestoria/Monster.h
  7. 2
      Adventures in Lestoria/MonsterData.cpp
  8. 13
      Adventures in Lestoria/Player.cpp
  9. 23
      Adventures in Lestoria/RUN_STRATEGY.cpp
  10. 2
      Adventures in Lestoria/ShootAfar.cpp
  11. 5
      Adventures in Lestoria/TODO.txt
  12. 2
      Adventures in Lestoria/Version.h
  13. 70
      Adventures in Lestoria/Wolf.cpp
  14. 4
      Adventures in Lestoria/assets/Campaigns/1_1_v2.tmx
  15. 14
      Adventures in Lestoria/assets/config/MonsterStrategies.txt
  16. 2
      Adventures in Lestoria/assets/config/audio/events.txt

@ -667,6 +667,7 @@
<ClCompile Include="util.cpp" /> <ClCompile Include="util.cpp" />
<ClCompile Include="Witch.cpp" /> <ClCompile Include="Witch.cpp" />
<ClCompile Include="Wizard.cpp" /> <ClCompile Include="Wizard.cpp" />
<ClCompile Include="Wolf.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="ClassDiagram2.cd" /> <None Include="ClassDiagram2.cd" />

@ -719,6 +719,9 @@
<ClCompile Include="Frog.cpp"> <ClCompile Include="Frog.cpp">
<Filter>Source Files\Monster Strategies</Filter> <Filter>Source Files\Monster Strategies</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Wolf.cpp">
<Filter>Source Files\Monster Strategies</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="cpp.hint" /> <None Include="cpp.hint" />

@ -46,6 +46,8 @@ enum BuffType{
BLOCK_SLOWDOWN, BLOCK_SLOWDOWN,
RESTORATION, RESTORATION,
RESTORATION_DURING_CAST, RESTORATION_DURING_CAST,
LOCKON_SPEEDBOOST, //Specifically used for wolves.
SPEEDBOOST,
}; };
class AiL; class AiL;

@ -41,6 +41,7 @@ All rights reserved.
#include "MonsterStrategyHelpers.h" #include "MonsterStrategyHelpers.h"
#include "util.h" #include "util.h"
#include "BulletTypes.h" #include "BulletTypes.h"
#include "SoundEffect.h"
INCLUDE_game INCLUDE_game
INCLUDE_BULLET_LIST INCLUDE_BULLET_LIST
@ -94,7 +95,7 @@ void Monster::STRATEGY::FROG(Monster&m,float fElapsedTime,std::string strategy){
if(m.F(A::LOCKON_WAITTIME)==0.0f){ if(m.F(A::LOCKON_WAITTIME)==0.0f){
m.F(A::LOCKON_WAITTIME)=ConfigFloat("Attack Duration"); m.F(A::LOCKON_WAITTIME)=ConfigFloat("Attack Duration");
vf2d tongueMaxRangePos=geom2d::line<float>(m.GetPos(),m.V(A::LOCKON_POS)).upoint(ConfigFloat("Tongue Max Range")/ConfigFloat("Range")); vf2d tongueMaxRangePos=geom2d::line<float>(m.GetPos(),m.V(A::LOCKON_POS)).upoint(ConfigFloat("Tongue Max Range")/ConfigFloat("Range"));
SoundEffect::PlaySFX("Slime Shoot",m.pos);
CreateBullet(FrogTongue)(m.pos,tongueMaxRangePos,ConfigFloat("Attack Duration"),m.GetAttack(),m.OnUpperLevel(),ConfigFloat("Tongue Knockback Strength"),false,ConfigPixel("Tongue Color"))EndBullet; CreateBullet(FrogTongue)(m.pos,tongueMaxRangePos,ConfigFloat("Attack Duration"),m.GetAttack(),m.OnUpperLevel(),ConfigFloat("Tongue Knockback Strength"),false,ConfigPixel("Tongue Color"))EndBullet;
m.PerformShootAnimation(); m.PerformShootAnimation();
m.I(A::PHASE)=2; m.I(A::PHASE)=2;
@ -104,6 +105,11 @@ void Monster::STRATEGY::FROG(Monster&m,float fElapsedTime,std::string strategy){
case 2:{ case 2:{
if(m.F(A::LOCKON_WAITTIME)==0.0f){ if(m.F(A::LOCKON_WAITTIME)==0.0f){
m.F(A::LOCKON_WAITTIME)=ConfigFloat("Attack Recovery Time"); m.F(A::LOCKON_WAITTIME)=ConfigFloat("Attack Recovery Time");
m.I(A::PHASE)=3;
}
}break;
case 3:{
if(m.F(A::LOCKON_WAITTIME)==0.0f){
m.I(A::PHASE)=0; m.I(A::PHASE)=0;
} }
}break; }break;

@ -89,9 +89,17 @@ int Monster::GetAttack(){
return int(mod_atk); return int(mod_atk);
} }
float Monster::GetMoveSpdMult(){ float Monster::GetMoveSpdMult(){
float mod_moveSpd=stats.A("Move Spd %"); float moveSpdPct=stats.A("Move Spd %")/100.f;
float mod_moveSpd=moveSpdPct;
for(Buff&b:GetBuffs(SLOWDOWN)){ for(Buff&b:GetBuffs(SLOWDOWN)){
mod_moveSpd-=stats.A("Move Spd %")*b.intensity; mod_moveSpd-=moveSpdPct*b.intensity;
}
for(Buff&b:GetBuffs(LOCKON_SPEEDBOOST)){
mod_moveSpd+=moveSpdPct*b.intensity;
}
for(Buff&b:GetBuffs(SPEEDBOOST)){
mod_moveSpd+=moveSpdPct*b.intensity;
} }
return mod_moveSpd; return mod_moveSpd;
} }

@ -235,6 +235,7 @@ private:
static void SLIMEKING(Monster&m,float fElapsedTime,std::string strategy); static void SLIMEKING(Monster&m,float fElapsedTime,std::string strategy);
static void RUN_AWAY(Monster&m,float fElapsedTime,std::string strategy); static void RUN_AWAY(Monster&m,float fElapsedTime,std::string strategy);
static void FROG(Monster&m,float fElapsedTime,std::string strategy); static void FROG(Monster&m,float fElapsedTime,std::string strategy);
static void WOLF(Monster&m,float fElapsedTime,std::string strategy);
}; };
}; };

@ -166,7 +166,7 @@ void MonsterData::InitializeMonsterData(){
DATA["Monsters"][MonsterName]["XP"].GetInt(), DATA["Monsters"][MonsterName]["XP"].GetInt(),
animations, animations,
drops, drops,
float(DATA["Monsters"][MonsterName]["MoveSpd"].GetReal())/100, float(DATA["Monsters"][MonsterName]["MoveSpd"].GetReal()),
float(DATA["Monsters"][MonsterName]["Size"].GetReal())/100, float(DATA["Monsters"][MonsterName]["Size"].GetReal())/100,
strategyName, strategyName,
DATA["Monsters"][MonsterName]["CollisionDmg"].GetInt() DATA["Monsters"][MonsterName]["CollisionDmg"].GetInt()

@ -232,13 +232,20 @@ const int Player::GetAttack(){
} }
float Player::GetMoveSpdMult(){ float Player::GetMoveSpdMult(){
float mod_moveSpd=GetStat("Move Spd %")/100.f; float moveSpdPct=GetStat("Move Spd %")/100.f;
float mod_moveSpd=moveSpdPct;
mod_moveSpd+=ItemAttribute::Get("Move Spd %",this); mod_moveSpd+=ItemAttribute::Get("Move Spd %",this);
for(const Buff&b:GetBuffs(BuffType::SLOWDOWN)){ for(const Buff&b:GetBuffs(BuffType::SLOWDOWN)){
mod_moveSpd-=mod_moveSpd*b.intensity; mod_moveSpd-=moveSpdPct*b.intensity;
} }
for(const Buff&b:GetBuffs(BuffType::BLOCK_SLOWDOWN)){ for(const Buff&b:GetBuffs(BuffType::BLOCK_SLOWDOWN)){
mod_moveSpd-=mod_moveSpd*b.intensity; mod_moveSpd-=moveSpdPct*b.intensity;
}
for(const Buff&b:GetBuffs(LOCKON_SPEEDBOOST)){
mod_moveSpd+=moveSpdPct*b.intensity;
}
for(const Buff&b:GetBuffs(SPEEDBOOST)){
mod_moveSpd+=moveSpdPct*b.intensity;
} }
return mod_moveSpd; return mod_moveSpd;
} }

@ -42,6 +42,18 @@ All rights reserved.
INCLUDE_DATA INCLUDE_DATA
INCLUDE_STRATEGY_DATA INCLUDE_STRATEGY_DATA
void Monster::InitializeStrategies(){
STRATEGY_DATA.insert("Run Towards",Monster::STRATEGY::RUN_TOWARDS);
STRATEGY_DATA.insert("Shoot Afar",Monster::STRATEGY::SHOOT_AFAR);
STRATEGY_DATA.insert("Turret",Monster::STRATEGY::TURRET);
STRATEGY_DATA.insert("Slime King",Monster::STRATEGY::SLIMEKING);
STRATEGY_DATA.insert("Run Away",Monster::STRATEGY::RUN_AWAY);
STRATEGY_DATA.insert("Frog",Monster::STRATEGY::FROG);
STRATEGY_DATA.insert("Wolf",Monster::STRATEGY::WOLF);
STRATEGY_DATA.SetInitialized();
}
int Monster::STRATEGY::_GetInt(Monster&m,std::string param,std::string strategy,int index){ int Monster::STRATEGY::_GetInt(Monster&m,std::string param,std::string strategy,int index){
if(DATA["Monsters"][m.name].HasProperty(param)){ if(DATA["Monsters"][m.name].HasProperty(param)){
return DATA["Monsters"][m.name].GetProperty(param).GetInt(index); return DATA["Monsters"][m.name].GetProperty(param).GetInt(index);
@ -73,15 +85,4 @@ Pixel Monster::STRATEGY::_GetPixel(Monster&m,std::string param,std::string strat
void Monster::STRATEGY::RUN_STRATEGY(Monster&m,float fElapsedTime){ void Monster::STRATEGY::RUN_STRATEGY(Monster&m,float fElapsedTime){
m.GetStrategy()(m,fElapsedTime,m.strategy); m.GetStrategy()(m,fElapsedTime,m.strategy);
}
void Monster::InitializeStrategies(){
STRATEGY_DATA.insert("Run Towards",Monster::STRATEGY::RUN_TOWARDS);
STRATEGY_DATA.insert("Shoot Afar",Monster::STRATEGY::SHOOT_AFAR);
STRATEGY_DATA.insert("Turret",Monster::STRATEGY::TURRET);
STRATEGY_DATA.insert("Slime King",Monster::STRATEGY::SLIMEKING);
STRATEGY_DATA.insert("Run Away",Monster::STRATEGY::RUN_AWAY);
STRATEGY_DATA.insert("Frog",Monster::STRATEGY::FROG);
STRATEGY_DATA.SetInitialized();
} }

@ -40,6 +40,7 @@ All rights reserved.
#include "AdventuresInLestoria.h" #include "AdventuresInLestoria.h"
#include "MonsterStrategyHelpers.h" #include "MonsterStrategyHelpers.h"
#include "util.h" #include "util.h"
#include "SoundEffect.h"
INCLUDE_BULLET_LIST INCLUDE_BULLET_LIST
INCLUDE_game INCLUDE_game
@ -52,6 +53,7 @@ void Monster::STRATEGY::SHOOT_AFAR(Monster&m,float fElapsedTime,std::string stra
if(m.queueShotTimer<0){ if(m.queueShotTimer<0){
m.queueShotTimer=0; m.queueShotTimer=0;
{ {
SoundEffect::PlaySFX("Slime Shoot",m.pos + vf2d{ 0,-4 });
BULLET_LIST.push_back(std::make_unique<Bullet>(Bullet(m.pos + vf2d{ 0,-4 }, geom2d::line(m.pos + vf2d{ 0,-4 }, game->GetPlayer()->GetPos()).vector().norm() * 24.f * float(ConfigInt("BulletSpeed"))/100.f, 12.f*ConfigInt("BulletSize")/100.f, m.GetAttack(),m.upperLevel,false, { uint8_t(ConfigIntArr("BulletColor",0)),uint8_t(ConfigIntArr("BulletColor",1)),uint8_t(ConfigIntArr("BulletColor",2)),uint8_t(ConfigIntArr("BulletColor",3) )},{ConfigInt("BulletSize")/100.f*8,ConfigInt("BulletSize")/100.f*8}))); BULLET_LIST.push_back(std::make_unique<Bullet>(Bullet(m.pos + vf2d{ 0,-4 }, geom2d::line(m.pos + vf2d{ 0,-4 }, game->GetPlayer()->GetPos()).vector().norm() * 24.f * float(ConfigInt("BulletSpeed"))/100.f, 12.f*ConfigInt("BulletSize")/100.f, m.GetAttack(),m.upperLevel,false, { uint8_t(ConfigIntArr("BulletColor",0)),uint8_t(ConfigIntArr("BulletColor",1)),uint8_t(ConfigIntArr("BulletColor",2)),uint8_t(ConfigIntArr("BulletColor",3) )},{ConfigInt("BulletSize")/100.f*8,ConfigInt("BulletSize")/100.f*8})));
} }
} }

@ -9,10 +9,6 @@ Settings Menu
-Upon pressing a key, check if the key is bound to another option, if so, -Upon pressing a key, check if the key is bound to another option, if so,
remove that bind from the list. Up to two keys may be binded per action. remove that bind from the list. Up to two keys may be binded per action.
-We have to save keybinds to the save file. -We have to save keybinds to the save file.
-Smooth Movement
-Click on title screen should not process as input immediately.
-Investigate why frame rate matters for intro screen.
January 31st January 31st
============ ============
@ -28,7 +24,6 @@ Implement the rest of the enemy types:
- Blue Frog - Blue Frog
Implement Ursule, Mother of Bears Boss Implement Ursule, Mother of Bears Boss
Story proofreading/correcting/storyboarding Story proofreading/correcting/storyboarding
- Add a command to play sound effects/music.
- Fix Keyboard/Controller Menu Navigation (Need clearly defined rules) - Fix Keyboard/Controller Menu Navigation (Need clearly defined rules)
- Game Controller Support - Game Controller Support
- Should use the Keybind structure that already exists. - Should use the Keybind structure that already exists.

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 0 #define VERSION_MAJOR 0
#define VERSION_MINOR 2 #define VERSION_MINOR 2
#define VERSION_PATCH 1 #define VERSION_PATCH 1
#define VERSION_BUILD 5760 #define VERSION_BUILD 5761
#define stringify(a) stringify_(a) #define stringify(a) stringify_(a)
#define stringify_(a) #a #define stringify_(a) #a

@ -0,0 +1,70 @@
#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 © 2023 The FreeType
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
All rights reserved.
*/
#pragma endregion
#include "Monster.h"
#include "AdventuresInLestoria.h"
#include "MonsterStrategyHelpers.h"
#include "util.h"
#include "BulletTypes.h"
#include "SoundEffect.h"
INCLUDE_game
INCLUDE_BULLET_LIST
using A=Attribute;
void Monster::STRATEGY::WOLF(Monster&m,float fElapsedTime,std::string strategy){
switch(m.I(A::PHASE)){
case 0:{ //Run towards the player.
float distToPlayer = geom2d::line<float>(game->GetPlayer()->GetPos(),m.GetPos()).length();
if(distToPlayer<=ConfigFloat("Lockon Range")){
m.I(A::PHASE)=1;
m.V(A::LOCKON_POS)=game->GetPlayer()->GetPos();
m.AddBuff(BuffType::)
}
RUN_TOWARDS(m,fElapsedTime,"Run Towards");
}break;
case 1:{ //Charge the player.
}break;
case 3:{
}break;
}
}

@ -1716,14 +1716,14 @@
</object> </object>
<object id="151" name="Green Slime" type="Monster" x="1056" y="4386"> <object id="151" name="Green Slime" type="Monster" x="1056" y="4386">
<properties> <properties>
<property name="Type" propertytype="MonsterName" value="Green Slime"/> <property name="Type" propertytype="MonsterName" value="Frog"/>
<property name="spawner" type="object" value="2"/> <property name="spawner" type="object" value="2"/>
</properties> </properties>
<point/> <point/>
</object> </object>
<object id="155" name="Green Slime" type="Monster" x="1050" y="4218"> <object id="155" name="Green Slime" type="Monster" x="1050" y="4218">
<properties> <properties>
<property name="Type" propertytype="MonsterName" value="Green Slime"/> <property name="Type" propertytype="MonsterName" value="Frog"/>
<property name="spawner" type="object" value="2"/> <property name="spawner" type="object" value="2"/>
</properties> </properties>
<point/> <point/>

@ -190,4 +190,18 @@ MonsterStrategy
# A multiplier for the knockback strength of the tongue. (1 is quite small) # A multiplier for the knockback strength of the tongue. (1 is quite small)
Tongue Knockback Strength = 2 Tongue Knockback Strength = 2
} }
Wolf
{
# How close the wolf has to be to lock on and charge the player.
Lockon Range = 400
# The speed boost percentage to increase by during the charge.
Lockon Speed Boost = 15%
# The speed boost percentage to increase by and the duration while disengaging.
Disengage Speed Boost = 30%, 3s
# The distance to disengage the player.
Disengage Range = 800
}
} }

@ -125,7 +125,7 @@ Events
{ {
# Specify file names, followed by volume % # Specify file names, followed by volume %
File[0] = slime_shoot.ogg, 100% File[0] = slime_shoot.ogg, 100%
File[1] = slime_shoot2.ogg, 100% File[1] = slime_shoot2.ogg, 80%
} }
Slime Walk Slime Walk
{ {

Loading…
Cancel
Save