Change the radius of ranger's auto attack to use pixel units instead of tile units. Remove hardcoded player acceleration on shooting a player arrow. Refactor monster animation system to incorporate custom animations as part of the main set of animations and handle future 4-way directional animations easily. Release Build 9115.

pull/57/head
sigonasr2 7 months ago
parent 76c1396fec
commit cdda8c9a99
  1. 3
      .gitignore
  2. 4
      Adventures in Lestoria/Adventures in Lestoria.vcxproj
  3. 12
      Adventures in Lestoria/Arrow.cpp
  4. 2
      Adventures in Lestoria/Bear.cpp
  5. 2
      Adventures in Lestoria/Boar.cpp
  6. 5
      Adventures in Lestoria/BulletTypes.h
  7. 130
      Adventures in Lestoria/Goblin_Bow.cpp
  8. 2
      Adventures in Lestoria/Goblin_Dagger.cpp
  9. 27
      Adventures in Lestoria/Monster.cpp
  10. 12
      Adventures in Lestoria/Monster.h
  11. 3
      Adventures in Lestoria/MonsterAttribute.h
  12. 186
      Adventures in Lestoria/MonsterData.cpp
  13. 17
      Adventures in Lestoria/MonsterData.h
  14. 4
      Adventures in Lestoria/MonsterStrategyHelpers.h
  15. 12
      Adventures in Lestoria/RUN_STRATEGY.cpp
  16. 2
      Adventures in Lestoria/Ranger.cpp
  17. 2
      Adventures in Lestoria/SlimeKing.cpp
  18. 12
      Adventures in Lestoria/Ursule.cpp
  19. 2
      Adventures in Lestoria/Version.h
  20. BIN
      Adventures in Lestoria/assets.zip
  21. 16
      Adventures in Lestoria/assets/Campaigns/2_1.tmx
  22. 19
      Adventures in Lestoria/assets/config/MonsterStrategies.txt
  23. 516
      Adventures in Lestoria/assets/config/Monsters.txt
  24. 66
      Adventures in Lestoria/assets/config/NPCs.txt
  25. 2
      Adventures in Lestoria/assets/config/classes/Ranger.txt
  26. 1
      Adventures in Lestoria/assets/config/gfx/gfx.txt
  27. BIN
      Adventures in Lestoria/assets/gamepack.pak
  28. BIN
      Adventures in Lestoria/assets/goblin_arrow.png
  29. BIN
      Adventures in Lestoria/assets/monsters/Goblin (Bow).xcf
  30. BIN
      Adventures in Lestoria/assets/rock.png
  31. 4
      Adventures in Lestoria/util.cpp
  32. 2
      Adventures in Lestoria/util.h
  33. BIN
      x64/Release/Adventures in Lestoria.exe

3
.gitignore vendored

@ -400,4 +400,5 @@ test.cpp
/x64/Release/Adventures in Lestoria.zip
/x64/Release/Adventures in Lestoria_web.zip
/x64/Release/AdventuresInLestoria_web.zip
packkey.cpp
packkey.cpp
desktop.ini

@ -712,6 +712,10 @@
</SubType>
</ClCompile>
<ClCompile Include="GameState.cpp" />
<ClCompile Include="Goblin_Bow.cpp">
<SubType>
</SubType>
</ClCompile>
<ClCompile Include="Goblin_Dagger.cpp" />
<ClCompile Include="InputHelper.cpp">
<SubType>

@ -44,11 +44,15 @@ All rights reserved.
INCLUDE_game
Arrow::Arrow(vf2d pos,vf2d targetPos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly,Pixel col)
:finalDistance(geom2d::line(pos,targetPos).length()*1.2f),acc(PI/2*"Ranger.Auto Attack.ArrowSpd"_F),
Arrow::Arrow(vf2d pos,vf2d targetPos,vf2d vel,float acc,float radius,int damage,bool upperLevel,bool friendly,Pixel col)
:finalDistance(geom2d::line(pos,targetPos).length()*1.2f),acc(acc),targetPos(targetPos),
Bullet(pos,vel,radius,damage,
"arrow.png",upperLevel,false,INFINITE,true,friendly,col){}
Arrow::Arrow(vf2d pos,vf2d targetPos,vf2d vel,const std::string_view gfx,float acc,float radius,int damage,bool upperLevel,bool friendly,Pixel col)
:finalDistance(geom2d::line(pos,targetPos).length()*1.2f),acc(acc),
Bullet(pos,vel,radius,damage,std::string(gfx),upperLevel,false,INFINITE,true,friendly,col){}
void Arrow::Update(float fElapsedTime){
float speed=vel.mag();
travelDistance+=speed*fElapsedTime;
@ -59,6 +63,10 @@ void Arrow::Update(float fElapsedTime){
}
}
void Arrow::PointToBestTargetPath(const int perceptionLevel){
//TODO: Figure out arrow target and spawn an arrow.
}
bool Arrow::PlayerHit(Player*player)
{
deactivated=true;

@ -76,7 +76,7 @@ void Monster::STRATEGY::BEAR(Monster&m,float fElapsedTime,std::string strategy){
if(m.F(A::CASTING_TIMER)==0.f){
m.I(A::PHASE)=2;
m.F(A::CASTING_TIMER)=ConfigFloat("Attack Animation Wait Time");
m.PerformOtherAnimation(0);
m.PerformAnimation("SLAM");
}
}break;
case 2:{

@ -73,7 +73,7 @@ void Monster::STRATEGY::BOAR(Monster&m,float fElapsedTime,std::string strategy){
m.UpdateFacingDirection(game->GetPlayer()->GetPos());
}else{
ScratchPhaseTransition:
m.PerformOtherAnimation(0);
m.PerformAnimation("SCRATCH");
m.F(A::CASTING_TIMER)=ConfigInt("Ground Scratch Count")*m.GetCurrentAnimation().GetTotalAnimationDuration();
m.phase=PhaseName::SCRATCH;
}

@ -67,8 +67,11 @@ struct Arrow:public Bullet{
float travelDistance=0;
float finalDistance=0;
float acc=PI/2*250;
Arrow(vf2d pos,vf2d targetPos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly=false,Pixel col=WHITE);
vf2d targetPos;
Arrow(vf2d pos,vf2d targetPos,vf2d vel,float acc,float radius,int damage,bool upperLevel,bool friendly=false,Pixel col=WHITE);
Arrow(vf2d pos,vf2d targetPos,vf2d vel,const std::string_view gfx,float acc,float radius,int damage,bool upperLevel,bool friendly=false,Pixel col=WHITE);
void Update(float fElapsedTime)override;
void PointToBestTargetPath(const int perceptionLevel);
bool PlayerHit(Player*player)override;
bool MonsterHit(Monster&monster)override;
};

@ -0,0 +1,130 @@
#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 "BulletTypes.h"
#include "util.h"
/*
Attack Strategie:
if range > 1000 move to a 850 range.
if range 1000-700. Stand still and shoot. (reload twice as fast)
if range between 500 and 700. Shoot and run in random direction while reloading without getting out of the 500 - 700 range
range < 500 while reloading try to get distance. still shoot if reload finishes
After every attack: reload takes 2 seconds.
before shooting takes 1 second.
*/
INCLUDE_game
INCLUDE_ANIMATION_DATA
INCLUDE_BULLET_LIST
using A=Attribute;
void Monster::STRATEGY::GOBLIN_BOW(Monster&m,float fElapsedTime,std::string strategy){
#pragma region Phase, Animation, and Helper function setup
enum PhaseName{
MOVE,
WINDUP,
};
enum class ANIMATION_OFFSET{
IDLE_ANIMATION=0,
SHOOT_ANIMATION=4,
};
auto SetFacingAnimation=[&](ANIMATION_OFFSET animation,vf2d target){
m.PerformAnimation("");
};
auto IsSpriteFlipped=[&](){return m.GetFacingDirection()==RIGHT;};
#pragma endregion
using enum ANIMATION_OFFSET;
m.F(A::ATTACK_COOLDOWN)+=fElapsedTime;
switch(m.phase){
case MOVE:{
float distToPlayer=m.GetDistanceFrom(game->GetPlayer()->GetPos());
const bool outsideMaxShootingRange=distToPlayer>=ConfigPixelsArr("Stand Still and Shoot Range",1);
auto PrepareToShoot=[&](){
m.phase=WINDUP;
m.F(A::SHOOT_TIMER)=ConfigFloat("Attack Windup Time");
SetFacingAnimation(SHOOT_ANIMATION,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(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");
}else{ //Only the stand still and shoot range remains...
PrepareToShoot();
}
}break;
case WINDUP:{
m.F(A::SHOOT_TIMER)-=fElapsedTime;
if(m.F(A::SHOOT_TIMER)<=0){
geom2d::line pointTowardsPlayer(m.GetPos(),game->GetPlayer()->GetPos());
vf2d extendedLine=pointTowardsPlayer.upoint(1.1f);
CreateBullet(Arrow)(m.GetPos(),extendedLine,pointTowardsPlayer.vector().norm()*ConfigFloat("Arrow Spd"),"goblin_arrow.png",PI/2*ConfigFloat("Arrow Spd"),ConfigFloat("Arrow Hitbox Radius"),m.GetAttack(),m.OnUpperLevel())EndBullet;
Arrow&arrow=static_cast<Arrow&>(*BULLET_LIST.back());
arrow.PointToBestTargetPath(0);
m.phase=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;
}
}

@ -75,7 +75,7 @@ void Monster::STRATEGY::GOBLIN_DAGGER(Monster&m,float fElapsedTime,std::string s
};
auto SetFacingAnimation=[&](ANIMATION_OFFSET animation,vf2d target){
m.PerformOtherAnimation(int(animation)+int(m.GetFacingDirectionToTarget(target)));
m.PerformAnimation("");
};
auto IsSpriteFlipped=[&](){return m.GetFacingDirection()==RIGHT;};

@ -66,14 +66,10 @@ std::map<std::string,Renderable*>MonsterData::imgs;
Monster::Monster(vf2d pos,MonsterData data,bool upperLevel,bool bossMob):
pos(pos),spawnPos(pos),hp(data.GetHealth()),size(data.GetSizeMult()),targetSize(data.GetSizeMult()),strategy(data.GetAIStrategy()),name(data.GetDisplayName()),upperLevel(upperLevel),isBoss(bossMob),facingDirection(DOWN){
bool firstAnimation=true;
for(std::string&anim:data.GetAnimations()){
for(const std::string&anim:data.GetAnimations()){
animation.AddState(anim,ANIMATION_DATA[anim]);
if(firstAnimation){
animation.ChangeState(internal_animState,anim);
firstAnimation=false;
}
}
PerformIdleAnimation();
stats.A("Health")=data.GetHealth();
stats.A("Attack")=data.GetAttack();
stats.A("Move Spd %")=data.GetMoveSpdMult();
@ -125,28 +121,28 @@ Animate2D::Frame Monster::GetFrame()const{
return animation.GetFrame(internal_animState);
}
void Monster::PerformJumpAnimation(){
animation.ChangeState(internal_animState,MONSTER_DATA[name].GetJumpAnimation());
PerformAnimation(MONSTER_DATA[name].GetJumpAnimation());
}
void Monster::PerformShootAnimation(){
animation.ChangeState(internal_animState,MONSTER_DATA[name].GetShootAnimation());
PerformAnimation(MONSTER_DATA[name].GetShootAnimation());
}
void Monster::PerformIdleAnimation(){
animation.ChangeState(internal_animState,MONSTER_DATA[name].GetIdleAnimation());
PerformAnimation(MONSTER_DATA[name].GetIdleAnimation());
}
void Monster::PerformNPCDownAnimation(){
animation.ChangeState(internal_animState,MONSTER_DATA[name].GetIdleAnimation());
PerformAnimation(MONSTER_DATA[name].GetIdleAnimation());
}
void Monster::PerformNPCUpAnimation(){
animation.ChangeState(internal_animState,MONSTER_DATA[name].GetJumpAnimation());
PerformAnimation(MONSTER_DATA[name].GetJumpAnimation());
}
void Monster::PerformNPCLeftAnimation(){
animation.ChangeState(internal_animState,MONSTER_DATA[name].GetShootAnimation());
PerformAnimation(MONSTER_DATA[name].GetShootAnimation());
}
void Monster::PerformNPCRightAnimation(){
animation.ChangeState(internal_animState,MONSTER_DATA[name].GetDeathAnimation());
PerformAnimation(MONSTER_DATA[name].GetDeathAnimation());
}
void Monster::PerformOtherAnimation(const uint8_t otherInd){
animation.ChangeState(internal_animState,MONSTER_DATA[name].GetAnimations()[4+otherInd]);
void Monster::PerformAnimation(const std::string_view animationName){
animation.ChangeState(internal_animState,std::string(animationName));
}
bool Monster::_SetX(float x,const bool monsterInvoked){
vf2d newPos={x,pos.y};
@ -879,7 +875,6 @@ const float Monster::GetDistanceFrom(vf2d target)const{
const Direction Monster::GetFacingDirectionToTarget(vf2d target)const{
float targetDirection=util::angleTo(GetPos(),target);
LOG(targetDirection<<std::endl);
if(targetDirection<=PI/4&&targetDirection>-PI/4)return Direction::EAST;
else if(targetDirection>=3*PI/4||targetDirection<-3*PI/4)return Direction::WEST;
else if(targetDirection<=3*PI/4&&targetDirection>PI/4)return Direction::SOUTH;

@ -56,13 +56,6 @@ class AiL;
enum class Attribute;
enum class MonsterAnimation{
IDLE,
JUMP,
SHOOT,
DEATH
};
class GameEvent;
class Monster:IAttributable{
@ -109,7 +102,7 @@ public:
void PerformNPCUpAnimation();
void PerformNPCLeftAnimation();
void PerformNPCRightAnimation();
void PerformOtherAnimation(const uint8_t otherInd);
void PerformAnimation(const std::string_view animationName);
const Animate2D::FrameSequence&GetCurrentAnimation()const;
const bool OnUpperLevel()const;
void Moved();
@ -219,6 +212,8 @@ private:
static int _GetInt(Monster&m,std::string param,std::string strategy,int index=0);
static float _GetFloat(Monster&m,std::string param,std::string strategy,int index=0);
static Pixel _GetPixel(Monster&m,std::string param,std::string strategy,int index=0);
//Converts unit distances to pixels. (Every 100 units = 24 pixels)
static double _GetPixels(Monster&m,std::string param,std::string strategy,int index=0);
static vf2d _GetVec(Monster&m,std::string param,std::string strategy,int index=0);
static const std::string&_GetString(Monster&m,std::string param,std::string strategy,int index=0);
static datafile _Get(Monster&m,std::string param,std::string strategy);
@ -235,6 +230,7 @@ private:
static void NPC(Monster&m,float fElapsedTime,std::string strategy);
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);
};
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.

@ -108,4 +108,7 @@ enum class Attribute{
INITIALIZED,
JUMP_MOVE_TO_TARGET_TIMER,
ATTACK_TYPE,
ATTACK_COOLDOWN,
RANDOM_DIRECTION,
RANDOM_RANGE
};

@ -51,7 +51,7 @@ std::map<std::string,MonsterData>MONSTER_DATA;
MonsterData::MonsterData()
:atk(0),collisionDmg(0),hp(0),moveSpd(0),size(0),strategy("Run Towards"){}
MonsterData::MonsterData(std::string name,int hp,int atk,const uint32_t xp,std::vector<std::string>animations,std::vector<MonsterDropData>drops,float moveSpd,float size,std::string strategy,int collisionDmg):
MonsterData::MonsterData(std::string name,int hp,int atk,const uint32_t xp,std::vector<MonsterDropData>drops,float moveSpd,float size,std::string strategy,int collisionDmg):
name(name),hp(hp),atk(atk),xp(xp),moveSpd(moveSpd),size(size),strategy(strategy),animations(animations),dropData(drops),collisionDmg(collisionDmg){}
void MonsterData::InitializeMonsterData(){
@ -60,12 +60,7 @@ void MonsterData::InitializeMonsterData(){
if(MONSTER_DATA.count(key)){
ERR("WARNING! A monster with the name "<<key<<" already exists in the database! Duplicates are not allowed.")
}
std::vector<std::string>animations{
MonsterName+"_IDLE",
MonsterName+"_JUMP",
MonsterName+"_SPIT",
MonsterName+"_DIE",
};
std::vector<std::string>animations;
MonsterData::imgs[MonsterName]=NEW Renderable();
const rcode imgLoadResult=MonsterData::imgs[MonsterName]->Load("assets/monsters/"+MonsterName+".png");
@ -94,78 +89,32 @@ void MonsterData::InitializeMonsterData(){
ANIMATION_DATA[state]=anim;
};
for(int i=0;i<animations.size();i++){
std::string animationConfigName="";
std::string imgName="";
switch(i){
case 0:{
animationConfigName="Idle";
imgName="_IDLE";
}break;
case 1:{
animationConfigName="Jump";
imgName="_JUMP";
}break;
case 2:{
animationConfigName="Shoot";
imgName="_SPIT";
}break;
case 3:{
animationConfigName="Death";
imgName="_DIE";
}break;
}
if(!DATA["Monsters"][MonsterName].HasProperty("Animations"))ERR(std::format("WARNING! Could not find any animations to load for monster {}! Please check the Monsters.txt configuration file!",MonsterName));
if(DATA["Monsters"][MonsterName]["Animations"].GetKeys().size()<4)ERR(std::format("WARNING! Monster {} does not have at least 4 animations. The animations should be defined in this order: a standing, walking, attack, and death animation",MonsterName));
for(size_t animationRow=0;auto&[animationName,size]:DATA["Monsters"][MonsterName]["Animations"]){
Animate2D::Style style=Animate2D::Style::Repeat;
if(DATA["Monsters"][MonsterName][animationConfigName+"Animation"].GetString(2)=="Repeat"){
if(DATA["Monsters"][MonsterName]["Animations"][animationName].GetString(2)=="Repeat"){
style=Animate2D::Style::Repeat;
}else
if(DATA["Monsters"][MonsterName][animationConfigName+"Animation"].GetString(2)=="OneShot"){
if(DATA["Monsters"][MonsterName]["Animations"][animationName].GetString(2)=="OneShot"){
style=Animate2D::Style::OneShot;
}else
if(DATA["Monsters"][MonsterName][animationConfigName+"Animation"].GetString(2)=="PingPong"){
if(DATA["Monsters"][MonsterName]["Animations"][animationName].GetString(2)=="PingPong"){
style=Animate2D::Style::PingPong;
}else
if(DATA["Monsters"][MonsterName][animationConfigName+"Animation"].GetString(2)=="Reverse"){
if(DATA["Monsters"][MonsterName]["Animations"][animationName].GetString(2)=="Reverse"){
style=Animate2D::Style::Reverse;
}else{
ERR(std::format("WARNING! Invalid Animation Style specified: {}",int(style)));
}
int frameCount=DATA["Monsters"][MonsterName][animationConfigName+"Animation"].GetInt(0);
int frameCount=DATA["Monsters"][MonsterName]["Animations"][animationName].GetInt(0);
vf2d frameSize=vf2d{float(DATA["Monsters"][MonsterName]["SheetFrameSize"].GetInt(0)),float(DATA["Monsters"][MonsterName]["SheetFrameSize"].GetInt(1))};
CreateHorizontalAnimationSequence(*MonsterData::imgs[MonsterName],frameCount,frameSize,MonsterName+imgName,i,AnimationData{float(DATA["Monsters"][MonsterName][animationConfigName+"Animation"].GetReal(1)),style});
}
CreateHorizontalAnimationSequence(*MonsterData::imgs[MonsterName],frameCount,frameSize,std::format("{}_{}",MonsterName,animationName),animationRow,AnimationData{float(DATA["Monsters"][MonsterName]["Animations"][animationName].GetReal(1)),style});
animations.push_back(animationName);
//Add additional custom animations defined in the config.
int animationCounter=0;
int row=4;
while(DATA["Monsters"][MonsterName].HasProperty("ANIMATION["+std::to_string(animationCounter)+"]")){
animations.push_back(MonsterName+"ANIMATION["+std::to_string(animationCounter)+"]");
#pragma region Parse Animation Data
Animate2D::Style style;
if(DATA["Monsters"][MonsterName]["ANIMATION["+std::to_string(animationCounter)+"]"].GetString(2)=="Repeat"){
style=Animate2D::Style::Repeat;
}else
if(DATA["Monsters"][MonsterName]["ANIMATION["+std::to_string(animationCounter)+"]"].GetString(2)=="OneShot"){
style=Animate2D::Style::OneShot;
}else
if(DATA["Monsters"][MonsterName]["ANIMATION["+std::to_string(animationCounter)+"]"].GetString(2)=="PingPong"){
style=Animate2D::Style::PingPong;
}else
if(DATA["Monsters"][MonsterName]["ANIMATION["+std::to_string(animationCounter)+"]"].GetString(2)=="Reverse"){
style=Animate2D::Style::Reverse;
}else{
ERR(std::format("WARNING! Invalid Animation Style specified: {}",int(style)));
}
int frameCount=DATA["Monsters"][MonsterName]["ANIMATION["+std::to_string(animationCounter)+"]"].GetInt(0);
vf2d frameSize=vf2d{float(DATA["Monsters"][MonsterName]["SheetFrameSize"].GetInt(0)),float(DATA["Monsters"][MonsterName]["SheetFrameSize"].GetInt(1))};
CreateHorizontalAnimationSequence(*MonsterData::imgs[MonsterName],frameCount,frameSize,MonsterName+"ANIMATION["+std::to_string(animationCounter)+"]",row,AnimationData{float(DATA["Monsters"][MonsterName]["ANIMATION["+std::to_string(animationCounter)+"]"].GetReal(1)),style});
#pragma endregion
row++;
animationCounter++;
animationRow++;
}
std::vector<MonsterDropData>drops;
@ -191,7 +140,6 @@ void MonsterData::InitializeMonsterData(){
DATA["Monsters"][MonsterName]["Health"].GetInt(),
DATA["Monsters"][MonsterName]["Attack"].GetInt(),
DATA["Monsters"][MonsterName]["XP"].GetInt(),
animations,
drops,
float(DATA["Monsters"][MonsterName]["MoveSpd"].GetReal()),
float(DATA["Monsters"][MonsterName]["Size"].GetReal())/100,
@ -199,6 +147,19 @@ void MonsterData::InitializeMonsterData(){
DATA["Monsters"][MonsterName]["CollisionDmg"].GetInt()
);
for(size_t animationRow=0;const std::string&animationName:animations){
if(!monster.animations.insert(animationName).second)ERR(std::format("WARNING! The Animation {} for Monster {} already exists! Animations should have unique names!",animationName,MonsterName));
switch(animationRow){
case 0:monster.idleAnimation=animationName;break;
case 1:monster.jumpAnimation=animationName;break;
case 2:monster.shootAnimation=animationName;break;
case 3:monster.deathAnimation=animationName;break;
}
animationRow++;
}
monster.hurtSound=hurtSound;
monster.deathSound=deathSound;
monster.walkSound=walkSound;
@ -260,78 +221,32 @@ void MonsterData::InitializeNPCData(){
ANIMATION_DATA[state]=anim;
};
for(int i=0;i<animations.size();i++){
std::string animationConfigName="";
std::string imgName="";
switch(i){
case 0:{
animationConfigName="Down";
imgName="_IDLE";
}break;
case 1:{
animationConfigName="Up";
imgName="_JUMP";
}break;
case 2:{
animationConfigName="Left";
imgName="_SPIT";
}break;
case 3:{
animationConfigName="Right";
imgName="_DIE";
}break;
}
if(!DATA["NPCs"][NPCName].HasProperty("Animations"))ERR(std::format("WARNING! Could not find any animations to load for monster {}! Please check the Monsters.txt configuration file!",NPCName));
if(DATA["NPCs"][NPCName]["Animations"].GetKeys().size()<4)ERR(std::format("WARNING! Monster {} does not have at least 4 animations. The animations should be defined in this order: a standing, walking, attack, and death animation",NPCName));
for(size_t animationRow=0;auto&[animationName,size]:DATA["NPCs"][NPCName]["Animations"]){
Animate2D::Style style=Animate2D::Style::Repeat;
if(DATA["NPCs"][NPCName][animationConfigName+"Animation"].GetString(2)=="Repeat"){
if(DATA["NPCs"][NPCName]["Animations"][animationName].GetString(2)=="Repeat"){
style=Animate2D::Style::Repeat;
}else
if(DATA["NPCs"][NPCName][animationConfigName+"Animation"].GetString(2)=="OneShot"){
if(DATA["NPCs"][NPCName]["Animations"][animationName].GetString(2)=="OneShot"){
style=Animate2D::Style::OneShot;
}else
if(DATA["NPCs"][NPCName][animationConfigName+"Animation"].GetString(2)=="PingPong"){
if(DATA["NPCs"][NPCName]["Animations"][animationName].GetString(2)=="PingPong"){
style=Animate2D::Style::PingPong;
}else
if(DATA["NPCs"][NPCName][animationConfigName+"Animation"].GetString(2)=="Reverse"){
if(DATA["NPCs"][NPCName]["Animations"][animationName].GetString(2)=="Reverse"){
style=Animate2D::Style::Reverse;
}else{
ERR(std::format("WARNING! Invalid Animation Style specified: {}",int(style)));
}
int frameCount=DATA["NPCs"][NPCName][animationConfigName+"Animation"].GetInt(0);
int frameCount=DATA["NPCs"][NPCName]["Animations"][animationName].GetInt(0);
vf2d frameSize=vf2d{float(DATA["NPCs"][NPCName]["SheetFrameSize"].GetInt(0)),float(DATA["NPCs"][NPCName]["SheetFrameSize"].GetInt(1))};
CreateHorizontalAnimationSequence(*MonsterData::imgs[NPCName],frameCount,frameSize,NPCName+imgName,i,AnimationData{float(DATA["NPCs"][NPCName][animationConfigName+"Animation"].GetReal(1)),style});
}
CreateHorizontalAnimationSequence(*MonsterData::imgs[NPCName],frameCount,frameSize,std::format("{}_{}",NPCName,animationName),animationRow,AnimationData{float(DATA["NPCs"][NPCName]["Animations"][animationName].GetReal(1)),style});
//Add additional custom animations defined in the config.
int animationCounter=0;
int row=4;
while(DATA["NPCs"][NPCName].HasProperty("ANIMATION["+std::to_string(animationCounter)+"]")){
animations.push_back(NPCName+"ANIMATION["+std::to_string(animationCounter)+"]");
#pragma region Parse Animation Data
Animate2D::Style style;
if(DATA["NPCs"][NPCName]["ANIMATION["+std::to_string(animationCounter)+"]"].GetString(2)=="Repeat"){
style=Animate2D::Style::Repeat;
}else
if(DATA["NPCs"][NPCName]["ANIMATION["+std::to_string(animationCounter)+"]"].GetString(2)=="OneShot"){
style=Animate2D::Style::OneShot;
}else
if(DATA["NPCs"][NPCName]["ANIMATION["+std::to_string(animationCounter)+"]"].GetString(2)=="PingPong"){
style=Animate2D::Style::PingPong;
}else
if(DATA["NPCs"][NPCName]["ANIMATION["+std::to_string(animationCounter)+"]"].GetString(2)=="Reverse"){
style=Animate2D::Style::Reverse;
}else{
ERR(std::format("WARNING! Invalid Animation Style specified: {}",int(style)));
}
int frameCount=DATA["NPCs"][NPCName]["ANIMATION["+std::to_string(animationCounter)+"]"].GetInt(0);
vf2d frameSize=vf2d{float(DATA["NPCs"][NPCName]["SheetFrameSize"].GetInt(0)),float(DATA["NPCs"][NPCName]["SheetFrameSize"].GetInt(1))};
CreateHorizontalAnimationSequence(*MonsterData::imgs[NPCName],frameCount,frameSize,NPCName+"ANIMATION["+std::to_string(animationCounter)+"]",row,AnimationData{float(DATA["NPCs"][NPCName]["ANIMATION["+std::to_string(animationCounter)+"]"].GetReal(1)),style});
#pragma endregion
row++;
animationCounter++;
animations.push_back(animationName);
animationRow++;
}
std::vector<MonsterDropData>drops;
@ -352,7 +267,20 @@ void MonsterData::InitializeNPCData(){
ERR("WARNING! Strategy for "<<NPCName<<" does not exist in strategy database!");
}
MonsterData monster(NPCName,health,attack,xp,animations,drops,moveSpd,size/100,strategyName,collisionDmg);
MonsterData monster(NPCName,health,attack,xp,drops,moveSpd,size/100,strategyName,collisionDmg);
for(size_t animationRow=0;const std::string&animationName:animations){
//if(!monster.animations.insert(animationName).second)ERR(std::format("WARNING! The Animation {} for Monster {} already exists! Animations should have unique names!",animationName,NPCName));
switch(animationRow){
case 0:monster.idleAnimation=animationName;break;
case 1:monster.jumpAnimation=animationName;break;
case 2:monster.shootAnimation=animationName;break;
case 3:monster.deathAnimation=animationName;break;
}
animationRow++;
}
monster.hurtSound=hurtSound;
monster.deathSound=deathSound;
@ -385,16 +313,16 @@ std::string MonsterData::GetDisplayName(){
}
std::string MonsterData::GetIdleAnimation(){
return animations[int(MonsterAnimation::IDLE)];
return idleAnimation;
}
std::string MonsterData::GetJumpAnimation(){
return animations[int(MonsterAnimation::JUMP)];
return jumpAnimation;
}
std::string MonsterData::GetShootAnimation(){
return animations[int(MonsterAnimation::SHOOT)];
return shootAnimation;
}
std::string MonsterData::GetDeathAnimation(){
return animations[int(MonsterAnimation::DEATH)];
return deathAnimation;
}
const std::vector<MonsterDropData>&MonsterData::GetDropData(){
return dropData;

@ -38,6 +38,7 @@ All rights reserved.
#pragma once
#include "DEFINES.h"
#include "Item.h"
#include <unordered_set>
INCLUDE_ITEM_DATA
@ -64,20 +65,22 @@ private:
uint32_t xp;
float moveSpd;//1.0=100%
float size;
std::vector<std::string> animations;
std::unordered_set<std::string>animations;
std::string idleAnimation="WARRIOR_IDLE_S"; //Represents the basic animation name, not the full animation name that ANIMATION_DATA indexes into!! (Ex. Not GREEN_SLIME_IDLE, but IDLE)
std::string jumpAnimation="WARRIOR_IDLE_S"; //Represents the basic animation name, not the full animation name that ANIMATION_DATA indexes into!! (Ex. Not GREEN_SLIME_JUMP, but JUMP)
std::string shootAnimation="WARRIOR_IDLE_S"; //Represents the basic animation name, not the full animation name that ANIMATION_DATA indexes into!! (Ex. Not GREEN_SLIME_SHOOT, but SHOOT)
std::string deathAnimation="WARRIOR_IDLE_S"; //Represents the basic animation name, not the full animation name that ANIMATION_DATA indexes into!! (Ex. Not GREEN_SLIME_DEATH, but DEATH)
std::string strategy;
int collisionDmg;
std::string jumpAnimation="WARRIOR_IDLE_S";
std::string shootAnimation="WARRIOR_IDLE_S";
std::string deathAnimation="WARRIOR_IDLE_S";
EventName hurtSound="";
EventName deathSound="";
EventName walkSound="";
std::vector<MonsterDropData> dropData;
bool isNPC=false;
bool fourWayDirectionalSprites=false; //When this flag is set, a monster has 4-way animations instead of the default 1-direction animation.
public:
MonsterData();
MonsterData(std::string name,int hp,int atk,const uint32_t xp,std::vector<std::string>animations,std::vector<MonsterDropData>drops,float moveSpd=1.0f,float size=1.0f,std::string strategy="Run Towards",int collisionDmg=0);
MonsterData(std::string name,int hp,int atk,const uint32_t xp,std::vector<MonsterDropData>drops,float moveSpd=1.0f,float size=1.0f,std::string strategy="Run Towards",int collisionDmg=0);
int GetHealth();
int GetAttack();
const uint32_t GetXP()const;
@ -93,7 +96,7 @@ public:
const EventName&GetDeathSound();
const EventName&GetWalkSound();
const bool IsNPC()const;
std::vector<std::string>GetAnimations(){
std::unordered_set<std::string>GetAnimations(){
return animations;
}
const std::vector<MonsterDropData>&GetDropData();
@ -101,4 +104,6 @@ public:
static void InitializeMonsterData();
static void InitializeNPCData();
static std::map<std::string,Renderable*>imgs;
const bool HasFourWaySprites()const;
void SetUsesFourWaySprites();
};

@ -39,9 +39,13 @@ All rights reserved.
#define ConfigInt(param) _GetInt(m,param,strategy)
#define ConfigFloat(param) _GetFloat(m,param,strategy)
#define ConfigPixel(param) _GetPixel(m,param,strategy)
//Converts unit distances to pixels. (Every 100 units = 24 pixels)
#define ConfigPixels(param) _GetPixels(m,param,strategy)
#define ConfigString(param) _GetString(m,param,strategy)
#define ConfigVec(param) _GetVec(m,param,strategy)
#define Config(param) _Get(m,param,strategy)
//Converts unit distances to pixels. (Every 100 units = 24 pixels)
#define ConfigPixelsArr(param,ind) _GetPixels(m,param,strategy,ind)
#define ConfigIntArr(param,ind) _GetInt(m,param,strategy,ind)
#define ConfigFloatArr(param,ind) _GetFloat(m,param,strategy,ind)
#define ConfigStringArr(param,ind) _GetString(m,param,strategy,ind)

@ -55,6 +55,7 @@ void Monster::InitializeStrategies(){
STRATEGY_DATA.insert("NPC",Monster::STRATEGY::NPC);
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.SetInitialized();
}
@ -120,6 +121,17 @@ Pixel Monster::STRATEGY::_GetPixel(Monster&m,std::string param,std::string strat
}
}
double Monster::STRATEGY::_GetPixels(Monster&m,std::string param,std::string strategy,int index){
if(m.IsNPC()&&DATA["NPCs"][m.name].HasProperty(param)){
return DATA["NPCs"][m.name].GetProperty(param).GetReal(index)/100.f*24;
}else
if(!m.IsNPC()&&DATA["Monsters"][m.name].HasProperty(param)){
return DATA["Monsters"][m.name].GetProperty(param).GetReal(index)/100.f*24;
} else {
return DATA["MonsterStrategy"][strategy].GetProperty(param).GetReal(index)/100.f*24;
}
}
void Monster::STRATEGY::RUN_STRATEGY(Monster&m,float fElapsedTime){
m.GetStrategy()(m,fElapsedTime,m.strategy);
}

@ -71,7 +71,7 @@ bool Ranger::AutoAttack(){
vf2d extendedLine=pointTowardsCursor.upoint(1.1f);
float angleToCursor=atan2(extendedLine.y-GetPos().y,extendedLine.x-GetPos().x);
attack_cooldown_timer=ARROW_ATTACK_COOLDOWN-GetAttackRecoveryRateReduction();
BULLET_LIST.push_back(std::make_unique<Arrow>(Arrow(GetPos(),extendedLine,vf2d{cos(angleToCursor)*"Ranger.Auto Attack.ArrowSpd"_F,float(sin(angleToCursor)*"Ranger.Auto Attack.ArrowSpd"_F-PI/8*"Ranger.Auto Attack.ArrowSpd"_F)}+movementVelocity/1.5f,"Ranger.Auto Attack.Radius"_F/100*12,int(GetAttack()*"Ranger.Auto Attack.DamageMult"_F),OnUpperLevel(),true)));
BULLET_LIST.push_back(std::make_unique<Arrow>(Arrow(GetPos(),extendedLine,vf2d{cos(angleToCursor)*"Ranger.Auto Attack.ArrowSpd"_F,float(sin(angleToCursor)*"Ranger.Auto Attack.ArrowSpd"_F-PI/8*"Ranger.Auto Attack.ArrowSpd"_F)}+movementVelocity/1.5f,PI/2*"Ranger.Auto Attack.ArrowSpd"_F,"Ranger.Auto Attack.Radius"_F,int(GetAttack()*"Ranger.Auto Attack.DamageMult"_F),OnUpperLevel(),true)));
SetState(State::SHOOT_ARROW);
SetAnimationBasedOnTargetingDirection(angleToCursor);
SoundEffect::PlaySFX("Ranger.Auto Attack.Sound"_S,SoundEffect::CENTERED);

@ -229,7 +229,7 @@ void Monster::STRATEGY::SLIMEKING(Monster&m,float fElapsedTime,std::string strat
}
if(m.GetState()==State::CASTING){
m.PerformOtherAnimation(0);
m.PerformAnimation("CHARGEUP");
if(m.F(A::CASTING_TIMER)==0){
m.SetState(State::NORMAL);
m.I(A::JUMP_COUNT)++;

@ -96,7 +96,7 @@ void Monster::STRATEGY::URSULE(Monster&m,float fElapsedTime,std::string strategy
case 1:{ //Run bear strategy in phase 1.
auto TransitionToPhase2=[&](){
m.phase=2;
m.PerformOtherAnimation(1);
m.PerformAnimation("SIT");
m.AddBuff(BARRIER_DAMAGE_REDUCTION,INFINITE,ConfigFloat("Phase 2.Barrier Damage Reduction")/100.f);
m.I(A::PHASE_REPEAT_COUNT)=ConfigInt("Phase 2.Wisp Pattern Spawn Count");
SoundEffect::PlaySFX("Ursule Phase Transition",SoundEffect::CENTERED);
@ -153,7 +153,7 @@ void Monster::STRATEGY::URSULE(Monster&m,float fElapsedTime,std::string strategy
BEAR(m,fElapsedTime,"Bear");
}break;
case 2:{
m.PerformOtherAnimation(2);
m.PerformAnimation("GLARE");
m.F(A::SHOOT_TIMER)=std::max(0.f,m.F(A::SHOOT_TIMER)-fElapsedTime);
#pragma region Environment Color Change Handling
@ -272,7 +272,7 @@ void Monster::STRATEGY::URSULE(Monster&m,float fElapsedTime,std::string strategy
if(m.GetRemainingHPPct()<=ConfigFloat("Phase 4.Change")/100.f){
auto TransitionToPhase5=[&](){
m.phase=5;
m.PerformOtherAnimation(1);
m.PerformAnimation("SIT");
SoundEffect::PlaySFX("Ursule Phase Transition",SoundEffect::CENTERED);
m.F(A::ENVIRONMENT_TIMER)=ConfigFloat("Phase 4.Environment Fade-out Time");
m.I(A::ENVIRONMENT_PHASE)=0;
@ -305,7 +305,7 @@ void Monster::STRATEGY::URSULE(Monster&m,float fElapsedTime,std::string strategy
if(m.F(A::CASTING_TIMER)==0.f){
m.F(A::CASTING_TIMER)=ConfigFloat("Phase 3.Charge Cast Time");
m.UpdateFacingDirection(geom2d::line<float>(m.GetPos(),game->GetPlayer()->GetPos()).vector());
m.PerformOtherAnimation(4);
m.PerformAnimation("CHARGE");
m.B(A::COLLIDED_WITH_PLAYER)=false;
}
}
@ -322,7 +322,7 @@ void Monster::STRATEGY::URSULE(Monster&m,float fElapsedTime,std::string strategy
m.target.y=std::clamp(m.target.y,0.f,float(game->GetCurrentMap().GetMapData().height*game->GetCurrentMap().GetMapData().tileheight));
m.F(A::TARGET_TIMER)=ConfigFloat("Phase 3.Charge Max Run Time");
m.F(A::CHARGE_COOLDOWN)=ConfigFloat("Phase 3.Charge Attack Cooldown");
m.PerformOtherAnimation(3);
m.PerformAnimation("CHARGING");
}
break;
}
@ -360,7 +360,7 @@ void Monster::STRATEGY::URSULE(Monster&m,float fElapsedTime,std::string strategy
}
}break;
case 5:{ //Final boss phase.
m.PerformOtherAnimation(2);
m.PerformAnimation("GLARE");
m.F(A::SHOOT_TIMER)=std::max(0.f,m.F(A::SHOOT_TIMER)-fElapsedTime);
#pragma region Environment Color Change Handling

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

Binary file not shown.

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.10.2" class="Map" orientation="orthogonal" renderorder="right-down" width="238" height="369" tilewidth="24" tileheight="24" infinite="0" nextlayerid="7" nextobjectid="27">
<map version="1.10" tiledversion="1.10.2" class="Map" orientation="orthogonal" renderorder="right-down" width="238" height="369" tilewidth="24" tileheight="24" infinite="0" nextlayerid="7" nextobjectid="29">
<properties>
<property name="Backdrop" propertytype="Backdrop" value="mountain_day"/>
<property name="Background Music" propertytype="BGM" value="foresty1_1"/>
@ -1881,21 +1881,11 @@
<object id="15" name="Spawn Group 1" type="SpawnGroup" x="4439" y="7869" width="496" height="424">
<ellipse/>
</object>
<object id="16" template="../maps/Monsters/Goblin (Dagger).tx" x="4599" y="8065">
<object id="27" template="../maps/Monsters/Goblin (Bow).tx" x="4587" y="8091">
<properties>
<property name="spawner" type="object" value="15"/>
</properties>
</object>
<object id="18" template="../maps/Monsters/Goblin (Dagger).tx" x="4711" y="8032">
<properties>
<property name="spawner" type="object" value="15"/>
</properties>
</object>
<object id="19" template="../maps/Monsters/Goblin (Dagger).tx" x="4646" y="8027">
<properties>
<property name="spawner" type="object" value="15"/>
</properties>
</object>
<object id="26" name="Player Spawn" type="PlayerSpawnLocation" x="265" y="1848" width="24" height="24"/>
<object id="28" name="Player Spawn" type="PlayerSpawnLocation" x="5112" y="8064" width="24" height="24"/>
</objectgroup>
</map>

@ -588,4 +588,23 @@ MonsterStrategy
Dagger Down Offset = -5,11
Dagger Left Offset = -10,6
}
Goblin Bow
{
Attack Reload Time = 2.0s
# How long it takes to prepare the attack once an attack is queued.
Attack Windup Time = 1.0s
Arrow Spd = 250
Arrow Hitbox Radius = 8
# When the monster will attempt to run away from target.
Run Away Range = 500
# Chooses a random direction within the confines of this range, stays within it.
Random Direction Range = 500,700
# Does not move and shoots from anywhere in these ranges.
Stand Still and Shoot Range = 700,1000
# Anything outside the max "Stand Still and Shoot Range" will cause the monster to move towards the target instead.
}
}

@ -18,25 +18,25 @@ Monsters
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
IdleAnimation = 10, 0.1, Repeat
JumpAnimation = 10, 0.06, Repeat
ShootAnimation = 10, 0.1, OneShot
DeathAnimation = 10, 0.1, OneShot
Animations
{
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# Animations must be defined in the same order as they are in their sprite sheets
# The First Four animations must represent a standing, walking, attack, and death animation. Their names are up to the creator.
IDLE = 10, 0.1, Repeat
JUMP = 10, 0.06, Repeat
SHOOT = 10, 0.1, OneShot
DEATH = 10, 0.1, OneShot
}
Hurt Sound = Monster Hurt
Death Sound = Slime Dead
Walk Sound = Slime Walk
# Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity
DROP[0] = Green Slime Remains,30%,1,1
DROP[1] = Minor Health Potion,5%,1,1
DROP[2] = Berries,3%,1,1
Hurt Sound = Monster Hurt
Death Sound = Slime Dead
Walk Sound = Slime Walk
#Additional custom animations go down below. Start with ANIMATION[0] Order is:
# File name, Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# NOTE: ANIMATION[0] will always be row 5 of an animation sheet, all numbers that follow are each below each other.
#ANIMATION[0] = 6, 0.1, Repeat
}
Blue Slime
{
@ -54,12 +54,17 @@ Monsters
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
IdleAnimation = 10, 0.1, Repeat
JumpAnimation = 10, 0.06, Repeat
ShootAnimation = 10, 0.1, Repeat
DeathAnimation = 10, 0.1, OneShot
Animations
{
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# Animations must be defined in the same order as they are in their sprite sheets
# The First Four animations must represent a standing, walking, attack, and death animation. Their names are up to the creator.
IDLE = 10, 0.1, Repeat
JUMP = 10, 0.06, Repeat
SHOOT = 10, 0.1, OneShot
DEATH = 10, 0.1, OneShot
}
Hurt Sound = Monster Hurt
Death Sound = Slime Dead
@ -69,11 +74,6 @@ Monsters
DROP[0] = Blue Slime Remains,30%,1,1
DROP[1] = Minor Mana Potion,5%,1,1
DROP[2] = Berries,5%,1,1
#Additional custom animations go down below. Start with ANIMATION[0] Order is:
# File name, Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# NOTE: ANIMATION[0] will always be row 5 of an animation sheet, all numbers that follow are each below each other.
#ANIMATION[0] = 6, 0.1, Repeat
}
Red Slime
{
@ -91,12 +91,17 @@ Monsters
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
IdleAnimation = 10, 0.1, Repeat
JumpAnimation = 10, 0.06, Repeat
ShootAnimation = 10, 0.1, OneShot
DeathAnimation = 10, 0.1, OneShot
Animations
{
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# Animations must be defined in the same order as they are in their sprite sheets
# The First Four animations must represent a standing, walking, attack, and death animation. Their names are up to the creator.
IDLE = 10, 0.1, Repeat
JUMP = 10, 0.06, Repeat
SHOOT = 10, 0.1, OneShot
DEATH = 10, 0.1, OneShot
}
Hurt Sound = Monster Hurt
Death Sound = Slime Dead
@ -106,11 +111,6 @@ Monsters
DROP[0] = Red Slime Remains,30%,1,1
DROP[1] = Minor Health Potion,5%,1,1
DROP[2] = Berries,5%,1,1
#Additional custom animations go down below. Start with ANIMATION[0] Order is:
# File name, Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# NOTE: ANIMATION[0] will always be row 5 of an animation sheet, all numbers that follow are each below each other.
#ANIMATION[0] = 6, 0.1, Repeat
}
Yellow Slime
{
@ -128,16 +128,17 @@ Monsters
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
IdleAnimation = 10, 0.1, Repeat
JumpAnimation = 10, 0.06, Repeat
ShootAnimation = 10, 0.1, OneShot
DeathAnimation = 10, 0.1, OneShot
Hurt Sound = Monster Hurt
Death Sound = Slime Dead
Walk Sound = Slime Walk
Animations
{
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# Animations must be defined in the same order as they are in their sprite sheets
# The First Four animations must represent a standing, walking, attack, and death animation. Their names are up to the creator.
IDLE = 10, 0.1, Repeat
JUMP = 10, 0.06, Repeat
SHOOT = 10, 0.1, OneShot
DEATH = 10, 0.1, OneShot
}
# Jump property overrides
JumpTimer = 10.0
@ -148,15 +149,14 @@ Monsters
# How much time remaining for the jump target being locked into place.
JumpLockinTargetTime = 0.2
Hurt Sound = Monster Hurt
Death Sound = Slime Dead
Walk Sound = Slime Walk
# Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity
DROP[0] = Yellow Slime Remains,30%,1,1
DROP[1] = Minor Recovery Potion,5%,1,1
DROP[2] = Berries,7%,1,2
#Additional custom animations go down below. Start with ANIMATION[0] Order is:
# File name, Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# NOTE: ANIMATION[0] will always be row 5 of an animation sheet, all numbers that follow are each below each other.
#ANIMATION[0] = 6, 0.1, Repeat
}
Flower Turret
{
@ -174,12 +174,17 @@ Monsters
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
IdleAnimation = 7, 0.1, PingPong
JumpAnimation = 1, 0.1, OneShot
ShootAnimation = 5, 0.1, OneShot
DeathAnimation = 5, 0.2, OneShot
Animations
{
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# Animations must be defined in the same order as they are in their sprite sheets
# The First Four animations must represent a standing, walking, attack, and death animation. Their names are up to the creator.
IDLE = 7, 0.1, PingPong
JUMP = 1, 0.1, OneShot
SHOOT = 5, 0.1, OneShot
DEATH = 5, 0.2, OneShot
}
Hurt Sound = Monster Hurt
Death Sound = Slime Dead
@ -189,11 +194,6 @@ Monsters
DROP[0] = Flower Petals,30%,1,1
DROP[1] = Berries,5%,1,1
DROP[2] = Bandages,10%,1,1
#Additional custom animations go down below. Start with ANIMATION[0] Order is:
# File name, Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# NOTE: ANIMATION[0] will always be row 5 of an animation sheet, all numbers that follow are each below each other.
#ANIMATION[0] = 6, 0.1, Repeat
}
Slime King
{
@ -212,12 +212,19 @@ Monsters
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
IdleAnimation = 10, 0.1, Repeat
JumpAnimation = 10, 0.06, Repeat
ShootAnimation = 10, 0.1, OneShot
DeathAnimation = 10, 0.1, OneShot
Animations
{
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# Animations must be defined in the same order as they are in their sprite sheets
# The First Four animations must represent a standing, walking, attack, and death animation. Their names are up to the creator.
IDLE = 10, 0.1, Repeat
JUMP = 10, 0.06, Repeat
SHOOT = 10, 0.1, OneShot
DEATH = 10, 0.1, OneShot
CHARGEUP = 10, 0.04, Repeat
}
Hurt Sound = Monster Hurt
Death Sound = Slime Dead
@ -225,11 +232,6 @@ Monsters
# Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity
DROP[0] = Ring of the Slime King,100%,1,1
#Additional custom animations go down below. Start with ANIMATION[0] Order is:
# File name, Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# NOTE: ANIMATION[0] will always be row 5 of an animation sheet, all numbers that follow are each below each other.
ANIMATION[0] = 10, 0.04, Repeat
}
Windhound
{
@ -247,12 +249,17 @@ Monsters
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
IdleAnimation = 3, 0.2, PingPong
JumpAnimation = 4, 0.06, PingPong
ShootAnimation = 10, 0.1, OneShot
DeathAnimation = 4, 0.1, OneShot
Animations
{
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# Animations must be defined in the same order as they are in their sprite sheets
# The First Four animations must represent a standing, walking, attack, and death animation. Their names are up to the creator.
IDLE = 3, 0.2, PingPong
JUMP = 4, 0.06, PingPong
SHOOT = 10, 0.1, OneShot
DEATH = 4, 0.1, OneShot
}
# Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity
DROP[0] = Windhound Skin,30%,1,1
@ -260,11 +267,6 @@ Monsters
Hurt Sound = Monster Hurt
Death Sound = Slime Dead
Walk Sound = Slime Walk
#Additional custom animations go down below. Start with ANIMATION[0] Order is:
# File name, Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# NOTE: ANIMATION[0] will always be row 5 of an animation sheet, all numbers that follow are each below each other.
#ANIMATION[0] = 6, 0.1, Repeat
}
Frog
{
@ -282,24 +284,24 @@ Monsters
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
IdleAnimation = 4, 0.13, PingPong
JumpAnimation = 10, 0.06, Repeat
ShootAnimation = 6, 0.15, PingPong
DeathAnimation = 6, 0.1, OneShot
# Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity
DROP[0] = Frog Skin,50%,1,1
Animations
{
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# Animations must be defined in the same order as they are in their sprite sheets
# The First Four animations must represent a standing, walking, attack, and death animation. Their names are up to the creator.
IDLE = 4, 0.13, PingPong
JUMP = 10, 0.06, Repeat
SHOOT = 6, 0.15, PingPong
DEATH = 6, 0.1, OneShot
}
Hurt Sound = Monster Hurt
Death Sound = Slime Dead
Walk Sound = Slime Walk
#Additional custom animations go down below. Start with ANIMATION[0] Order is:
# File name, Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# NOTE: ANIMATION[0] will always be row 5 of an animation sheet, all numbers that follow are each below each other.
#ANIMATION[0] = 6, 0.1, Repeat
# Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity
DROP[0] = Frog Skin,50%,1,1
}
Bear
{
@ -318,24 +320,25 @@ Monsters
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
IdleAnimation = 4, 0.3, Repeat
JumpAnimation = 5, 0.2, Repeat
ShootAnimation = 3, 0.2, OneShot
DeathAnimation = 3, 0.15, OneShot
# Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity
DROP[0] = Bear Blood,10%,1,2
DROP[1] = Bear Claw,30%,1,1
Animations
{
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# Animations must be defined in the same order as they are in their sprite sheets
# The First Four animations must represent a standing, walking, attack, and death animation. Their names are up to the creator.
IDLE = 4, 0.3, Repeat
JUMP = 5, 0.2, Repeat
SHOOT = 3, 0.2, OneShot
DEATH = 3, 0.15, OneShot
SLAM = 4, 0.2, OneShot
}
Hurt Sound = Monster Hurt
Death Sound = Slime Dead
Walk Sound = Slime Walk
#Additional custom animations go down below. Start with ANIMATION[0] Order is:
# File name, Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# NOTE: ANIMATION[0] will always be row 5 of an animation sheet, all numbers that follow are each below each other.
ANIMATION[0] = 4, 0.2, OneShot
# Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity
DROP[0] = Bear Blood,10%,1,2
DROP[1] = Bear Claw,30%,1,1
}
Ursule, Mother of Bears
{
@ -377,12 +380,22 @@ Monsters
#Size of each animation frame
SheetFrameSize = 26,26
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
IdleAnimation = 4, 0.3, Repeat
JumpAnimation = 5, 0.2, Repeat
ShootAnimation = 3, 0.2, OneShot
DeathAnimation = 3, 0.15, OneShot
Animations
{
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# Animations must be defined in the same order as they are in their sprite sheets
# The First Four animations must represent a standing, walking, attack, and death animation. Their names are up to the creator.
IDLE = 4, 0.3, Repeat
JUMP = 5, 0.2, Repeat
SHOOT = 3, 0.2, OneShot
DEATH = 3, 0.15, OneShot
SLAM = 4, 0.1, OneShot
SIT = 6, 0.15, OneShot
GLARE = 2, 0.2, Reverse
CHARGING = 5, 0.1, Repeat
CHARGE = 4, 0.3, Repeat
}
# Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity
DROP[0] = Ring of the Bear,100%,1,1
@ -392,15 +405,6 @@ Monsters
Hurt Sound = Monster Hurt
Death Sound = Ursule Dead
Walk Sound = Slime Walk
#Additional custom animations go down below. Start with ANIMATION[0] Order is:
# File name, Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# NOTE: ANIMATION[0] will always be row 5 of an animation sheet, all numbers that follow are each below each other.
ANIMATION[0] = 4, 0.1, OneShot
ANIMATION[1] = 6, 0.15, OneShot
ANIMATION[2] = 2, 0.2, Reverse
ANIMATION[3] = 5, 0.1, Repeat
ANIMATION[4] = 4, 0.3, Repeat
}
Bun
{
@ -418,12 +422,17 @@ Monsters
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
IdleAnimation = 10, 0.1, Repeat
JumpAnimation = 10, 0.06, Repeat
ShootAnimation = 10, 0.05, Repeat
DeathAnimation = 10, 0.1, OneShot
Animations
{
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# Animations must be defined in the same order as they are in their sprite sheets
# The First Four animations must represent a standing, walking, attack, and death animation. Their names are up to the creator.
IDLE = 10, 0.1, Repeat
JUMP = 10, 0.06, Repeat
SHOOT = 10, 0.1, OneShot
DEATH = 10, 0.1, OneShot
}
Range = 200
CloseInRange = 600
@ -440,11 +449,6 @@ Monsters
# Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity
DROP[0] = Slimy Bun,100%,1,1
#Additional custom animations go down below. Start with ANIMATION[0] Order is:
# File name, Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# NOTE: ANIMATION[0] will always be row 5 of an animation sheet, all numbers that follow are each below each other.
#ANIMATION[0] = 6, 0.1, Repeat
}
Boar
{
@ -462,12 +466,18 @@ Monsters
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
IdleAnimation = 1, 0.3, Repeat
JumpAnimation = 1, 0.2, Repeat
ShootAnimation = 1, 0.2, OneShot
DeathAnimation = 1, 0.15, OneShot
Animations
{
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# Animations must be defined in the same order as they are in their sprite sheets
# The First Four animations must represent a standing, walking, attack, and death animation. Their names are up to the creator.
IDLE = 1, 0.3, Repeat
JUMP = 1, 0.2, Repeat
SHOOT = 1, 0.2, OneShot
DEATH = 1, 0.15, OneShot
SCRATCH = 4, 0.2, OneShot
}
# Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity
# DROP[0] = Ring of the Bear,100%,1,1
@ -475,12 +485,6 @@ Monsters
Hurt Sound = Monster Hurt
Death Sound = Slime Dead
Walk Sound = Slime Walk
#Additional custom animations go down below. Start with ANIMATION[0] Order is:
# File name, Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# NOTE: ANIMATION[0] will always be row 5 of an animation sheet, all numbers that follow are each below each other.
# Scratch animation.
ANIMATION[0] = 4, 0.2, OneShot
}
Goblin (Dagger)
{
@ -501,12 +505,21 @@ Monsters
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
IdleAnimation = 1, 0.3, Repeat
JumpAnimation = 1, 0.2, Repeat
ShootAnimation = 1, 0.2, OneShot
DeathAnimation = 1, 0.15, OneShot
Animations
{
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# Animations must be defined in the same order as they are in their sprite sheets
# The First Four animations must represent a standing, walking, attack, and death animation. Their names are up to the creator.
IDLE = 1, 0.3, Repeat
JUMP = 1, 0.2, Repeat
SHOOT = 1, 0.2, OneShot
DEATH = 1, 0.15, OneShot
STAB = 1, 0.1, OneShot
STABBING = 2, 0.1, PingPong
SLASH = 1, 0.1, OneShot
SLASHING = 2, 0.1, PingPong
}
# Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity
# DROP[0] = Ring of the Bear,100%,1,1
@ -514,50 +527,6 @@ Monsters
Hurt Sound = Monster Hurt
Death Sound = Slime Dead
Walk Sound = Slime Walk
#Additional custom animations go down below. Start with ANIMATION[0] Order is:
# File name, Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# NOTE: ANIMATION[0] will always be row 5 of an animation sheet, all numbers that follow are each below each other.
# Up Stab Windup
ANIMATION[0] = 1, 0.1, OneShot
# Right Stab Windup
ANIMATION[1] = 1, 0.1, OneShot
# Down Stab Windup
ANIMATION[2] = 1, 0.1, OneShot
# Left Stab Windup
ANIMATION[3] = 1, 0.1, OneShot
# Up Stab
ANIMATION[4] = 2, 0.1, PingPong
# Right Stab
ANIMATION[5] = 2, 0.1, PingPong
# Down Stab
ANIMATION[6] = 2, 0.1, PingPong
# Left Stab
ANIMATION[7] = 2, 0.1, PingPong
# Up Slash Windup
ANIMATION[8] = 1, 0.1, OneShot
# Right Slash Windup
ANIMATION[9] = 1, 0.1, OneShot
# Down Slash Windup
ANIMATION[10] = 1, 0.1, OneShot
# Left Slash Windup
ANIMATION[11] = 1, 0.1, OneShot
# Up Slash
ANIMATION[12] = 2, 0.1, PingPong
# Right Slash
ANIMATION[13] = 2, 0.1, PingPong
# Down Slash
ANIMATION[14] = 2, 0.1, PingPong
# Left Slash
ANIMATION[15] = 2, 0.1, PingPong
# Up Idle
ANIMATION[16] = 1, 0.1, PingPong
# Right Idle
ANIMATION[17] = 1, 0.1, PingPong
# Down Idle
ANIMATION[18] = 1, 0.1, PingPong
# Left Idle
ANIMATION[19] = 1, 0.1, PingPong
}
Goblin (Bow)
{
@ -571,28 +540,33 @@ Monsters
XP = 17
Strategy = Run Towards
Strategy = Goblin Bow
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
IdleAnimation = 1, 0.3, Repeat
JumpAnimation = 1, 0.2, Repeat
ShootAnimation = 1, 0.2, OneShot
DeathAnimation = 1, 0.15, OneShot
# Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity
# DROP[0] = Ring of the Bear,100%,1,1
Animations
{
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# Animations must be defined in the same order as they are in their sprite sheets
# The First Four animations must represent a standing, walking, attack, and death animation. Their names are up to the creator.
IDLE = 1, 0.1, Repeat
WALK = 1, 0.2, Repeat
SHOOT = 3, 0.3, OneShot
DEATH = 1, 0.15, OneShot
STAB = 1, 0.1, OneShot
STABBING = 2, 0.1, PingPong
SLASH = 1, 0.1, OneShot
SLASHING = 2, 0.1, PingPong
}
Hurt Sound = Monster Hurt
Death Sound = Slime Dead
Walk Sound = Slime Walk
#Additional custom animations go down below. Start with ANIMATION[0] Order is:
# File name, Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# NOTE: ANIMATION[0] will always be row 5 of an animation sheet, all numbers that follow are each below each other.
# ANIMATION[0] = 4, 0.1, OneShot
# Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity
# DROP[0] = Ring of the Bear,100%,1,1
}
Goblin (Bombs)
{
@ -610,24 +584,24 @@ Monsters
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
IdleAnimation = 1, 0.3, Repeat
JumpAnimation = 1, 0.2, Repeat
ShootAnimation = 1, 0.2, OneShot
DeathAnimation = 1, 0.15, OneShot
# Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity
# DROP[0] = Ring of the Bear,100%,1,1
Animations
{
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# Animations must be defined in the same order as they are in their sprite sheets
# The First Four animations must represent a standing, walking, attack, and death animation. Their names are up to the creator.
IDLE = 1, 0.3, Repeat
JUMP = 1, 0.2, Repeat
SHOOT = 1, 0.2, OneShot
DEATH = 1, 0.15, OneShot
}
Hurt Sound = Monster Hurt
Death Sound = Slime Dead
Walk Sound = Slime Walk
#Additional custom animations go down below. Start with ANIMATION[0] Order is:
# File name, Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# NOTE: ANIMATION[0] will always be row 5 of an animation sheet, all numbers that follow are each below each other.
# ANIMATION[0] = 4, 0.1, OneShot
# Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity
# DROP[0] = Ring of the Bear,100%,1,1
}
Goblin Boar Rider
{
@ -645,24 +619,24 @@ Monsters
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
IdleAnimation = 1, 0.3, Repeat
JumpAnimation = 1, 0.2, Repeat
ShootAnimation = 1, 0.2, OneShot
DeathAnimation = 1, 0.15, OneShot
# Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity
# DROP[0] = Ring of the Bear,100%,1,1
Animations
{
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# Animations must be defined in the same order as they are in their sprite sheets
# The First Four animations must represent a standing, walking, attack, and death animation. Their names are up to the creator.
IDLE = 1, 0.3, Repeat
JUMP = 1, 0.2, Repeat
SHOOT = 1, 0.2, OneShot
DEATH = 1, 0.15, OneShot
}
Hurt Sound = Monster Hurt
Death Sound = Slime Dead
Walk Sound = Slime Walk
#Additional custom animations go down below. Start with ANIMATION[0] Order is:
# File name, Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# NOTE: ANIMATION[0] will always be row 5 of an animation sheet, all numbers that follow are each below each other.
# ANIMATION[0] = 4, 0.1, OneShot
# Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity
# DROP[0] = Ring of the Bear,100%,1,1
}
Hawk
{
@ -680,24 +654,24 @@ Monsters
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
IdleAnimation = 1, 0.3, Repeat
JumpAnimation = 1, 0.2, Repeat
ShootAnimation = 1, 0.2, OneShot
DeathAnimation = 1, 0.15, OneShot
# Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity
# DROP[0] = Ring of the Bear,100%,1,1
Animations
{
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# Animations must be defined in the same order as they are in their sprite sheets
# The First Four animations must represent a standing, walking, attack, and death animation. Their names are up to the creator.
IDLE = 1, 0.3, Repeat
JUMP = 1, 0.2, Repeat
SHOOT = 1, 0.2, OneShot
DEATH = 1, 0.15, OneShot
}
Hurt Sound = Monster Hurt
Death Sound = Slime Dead
Walk Sound = Slime Walk
#Additional custom animations go down below. Start with ANIMATION[0] Order is:
# File name, Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# NOTE: ANIMATION[0] will always be row 5 of an animation sheet, all numbers that follow are each below each other.
# ANIMATION[0] = 4, 0.1, OneShot
# Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity
# DROP[0] = Ring of the Bear,100%,1,1
}
Stone Elemental
{
@ -715,23 +689,23 @@ Monsters
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
IdleAnimation = 1, 0.3, Repeat
JumpAnimation = 1, 0.2, Repeat
ShootAnimation = 1, 0.2, OneShot
DeathAnimation = 1, 0.15, OneShot
# Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity
# DROP[0] = Ring of the Bear,100%,1,1
Animations
{
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# Animations must be defined in the same order as they are in their sprite sheets
# The First Four animations must represent a standing, walking, attack, and death animation. Their names are up to the creator.
IDLE = 1, 0.3, Repeat
JUMP = 1, 0.2, Repeat
SHOOT = 1, 0.2, OneShot
DEATH = 1, 0.15, OneShot
}
Hurt Sound = Monster Hurt
Death Sound = Slime Dead
Walk Sound = Slime Walk
#Additional custom animations go down below. Start with ANIMATION[0] Order is:
# File name, Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# NOTE: ANIMATION[0] will always be row 5 of an animation sheet, all numbers that follow are each below each other.
# ANIMATION[0] = 4, 0.2, OneShot
# Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity
# DROP[0] = Ring of the Bear,100%,1,1
}
}

@ -8,21 +8,21 @@ NPCs
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
DownAnimation = 1, 0.1, OneShot
UpAnimation = 1, 0.1, OneShot
LeftAnimation = 1, 0.1, OneShot
RightAnimation = 1, 0.1, OneShot
Animations
{
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# Animations must be defined in the same order as they are in their sprite sheets
# The First Four animations must represent a standing, walking, attack, and death animation. Their names are up to the creator.
DOWN = 1, 0.1, OneShot
UP = 1, 0.1, OneShot
LEFT = 1, 0.1, OneShot
RIGHT = 1, 0.1, OneShot
}
Hurt Sound = Monster Hurt
Death Sound = Slime Dead
Walk Sound = Slime Walk
#Additional custom animations go down below. Start with ANIMATION[0] Order is:
# File name, Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# NOTE: ANIMATION[0] will always be row 5 of an animation sheet, all numbers that follow are each below each other.
#ANIMATION[0] = 6, 0.1, Repeat
}
Sherman
{
@ -32,21 +32,21 @@ NPCs
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
DownAnimation = 1, 0.1, OneShot
UpAnimation = 1, 0.1, OneShot
LeftAnimation = 1, 0.1, OneShot
RightAnimation = 1, 0.1, OneShot
Animations
{
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# Animations must be defined in the same order as they are in their sprite sheets
# The First Four animations must represent a standing, walking, attack, and death animation. Their names are up to the creator.
DOWN = 1, 0.1, OneShot
UP = 1, 0.1, OneShot
LEFT = 1, 0.1, OneShot
RIGHT = 1, 0.1, OneShot
}
Hurt Sound = Monster Hurt
Death Sound = Slime Dead
Walk Sound = Slime Walk
#Additional custom animations go down below. Start with ANIMATION[0] Order is:
# File name, Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# NOTE: ANIMATION[0] will always be row 5 of an animation sheet, all numbers that follow are each below each other.
#ANIMATION[0] = 6, 0.1, Repeat
}
Traveling Merchant
{
@ -54,20 +54,20 @@ NPCs
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
DownAnimation = 1, 0.1, OneShot
UpAnimation = 1, 0.1, OneShot
LeftAnimation = 1, 0.1, OneShot
RightAnimation = 1, 0.1, OneShot
Animations
{
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# Animations must be defined in the same order as they are in their sprite sheets
# The First Four animations must represent a standing, walking, attack, and death animation. Their names are up to the creator.
DOWN = 1, 0.1, OneShot
UP = 1, 0.1, OneShot
LEFT = 1, 0.1, OneShot
RIGHT = 1, 0.1, OneShot
}
Hurt Sound = Monster Hurt
Death Sound = Slime Dead
Walk Sound = Slime Walk
#Additional custom animations go down below. Start with ANIMATION[0] Order is:
# File name, Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
# NOTE: ANIMATION[0] will always be row 5 of an animation sheet, all numbers that follow are each below each other.
#ANIMATION[0] = 6, 0.1, Repeat
}
}

@ -15,7 +15,7 @@ Ranger
Auto Attack
{
DamageMult = 1
Radius = 100
Radius = 12
Cooldown = 0.6
# Whether or not this ability cancels casts.
CancelCast = 0

@ -88,6 +88,7 @@ Images
GFX_Checkmark = checkmark.png
GFX_DaggerStab = dagger_stab.png
GFX_GoblinSwordSlash = goblin_sword_slash.png
GFX_GoblinArrow = goblin_arrow.png
# Ability Icons
GFX_Warrior_BattleCry_Icon = Ability Icons/battlecry.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 699 B

@ -52,6 +52,10 @@ int util::random(){
return distrib(rng);
}
const float util::random_range(const float min,const float max){
return random(max-min)+min;
}
vf2d util::pointTo(vf2d posFrom,vf2d posTo){
return geom2d::line(posFrom,posTo).vector().norm();
}

@ -44,6 +44,8 @@ All rights reserved.
namespace olc::util{
//Returns 0-range (as a float).
float random(float range);
//Returns a random float value min(inclusive) to max(exclusive).
const float random_range(const float min,const float max);
//Returns 0-32767 (as an int).
int random();
//Returns a normalized vector pointing from posFrom towards posTo.

Loading…
Cancel
Save