Switch controller auto-targeting to use logic from Hurt function. This means the auto targeting tries to ensure it hits some target, but prefers a currently vulnerable target over an invulnerable / unhittable one. Cleanup the code to use std::optional. Add in a helper function to get nearest monster. Apply Mark to nearest selected target when Trapper Mark Target ability is used. Release Build 10275.
This commit is contained in:
parent
60b45cf6b1
commit
b3c5894be7
@ -44,22 +44,32 @@ INCLUDE_ANIMATION_DATA
|
||||
INCLUDE_game
|
||||
|
||||
Effect::Effect(vf2d pos,float lifetime,std::string imgFile,bool upperLevel,float size,float fadeout,vf2d spd,Pixel col,float rotation,float rotationSpd,bool additiveBlending)
|
||||
:Effect::Effect(pos,lifetime,imgFile,upperLevel,vf2d{size,size},fadeout,spd,col,rotation,rotationSpd,additiveBlending){
|
||||
:Effect::Effect(pos,lifetime,imgFile,upperLevel,0.f,fadeout,vf2d{size,size},spd,col,rotation,rotationSpd,additiveBlending){
|
||||
this->animation.AddState(imgFile,ANIMATION_DATA.at(imgFile));
|
||||
}
|
||||
|
||||
Effect::Effect(vf2d pos,float lifetime,std::string imgFile,bool upperLevel,vf2d size,float fadeout,vf2d spd,Pixel col,float rotation,float rotationSpd,bool additiveBlending)
|
||||
:pos(pos),lifetime(lifetime),upperLevel(upperLevel),size(size),fadeout(fadeout),original_fadeoutTime(fadeout),spd(spd),col(col),rotation(rotation),rotationSpd(rotationSpd),additiveBlending(additiveBlending){
|
||||
:pos(pos),lifetime(lifetime),upperLevel(upperLevel),size(size),original_fadeInTime(fadein),fadeout(fadeout),original_fadeOutTime(fadeout),spd(spd),col(col),rotation(rotation),rotationSpd(rotationSpd),additiveBlending(additiveBlending){
|
||||
this->animation.AddState(imgFile,ANIMATION_DATA.at(imgFile));
|
||||
}
|
||||
|
||||
Effect::Effect(vf2d pos,float lifetime,std::string imgFile,bool upperLevel,float fadein,float fadeout,vf2d size,vf2d spd,Pixel col,float rotation,float rotationSpd,bool additiveBlending)
|
||||
:pos(pos),lifetime(lifetime),upperLevel(upperLevel),size(size),fadein(fadein),original_fadeInTime(fadein),fadeout(fadeout),original_fadeOutTime(fadeout),spd(spd),col(col),rotation(rotation),rotationSpd(rotationSpd),additiveBlending(additiveBlending){
|
||||
this->animation.AddState(imgFile,ANIMATION_DATA.at(imgFile));
|
||||
}
|
||||
|
||||
bool Effect::Update(float fElapsedTime){
|
||||
lifetime-=fElapsedTime;
|
||||
if(lifetime<=0){
|
||||
fadeout-=fElapsedTime;
|
||||
if(fadeout<=0){
|
||||
dead=true;
|
||||
return false;
|
||||
aliveTime+=fElapsedTime;
|
||||
if(fadein<original_fadeInTime){
|
||||
fadein=std::min(original_fadeInTime,fadein+fElapsedTime);
|
||||
}else{
|
||||
lifetime-=fElapsedTime;
|
||||
if(lifetime<=0){
|
||||
fadeout-=fElapsedTime;
|
||||
if(fadeout<=0){
|
||||
dead=true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
rotation+=rotationSpd*fElapsedTime;
|
||||
@ -70,10 +80,14 @@ bool Effect::Update(float fElapsedTime){
|
||||
|
||||
void Effect::Draw()const{
|
||||
if(additiveBlending)game->SetDecalMode(DecalMode::ADDITIVE);
|
||||
if(fadeout==0){
|
||||
if(fadeout==0&&fadein==original_fadeInTime){
|
||||
game->view.DrawPartialRotatedDecal(pos,GetFrame().GetSourceImage()->Decal(),rotation,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,size,col);
|
||||
} else {
|
||||
game->view.DrawPartialRotatedDecal(pos,GetFrame().GetSourceImage()->Decal(),rotation,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,size,{col.r,col.g,col.b,uint8_t(fadeout/original_fadeoutTime*col.a)});
|
||||
}else
|
||||
if(fadein==original_fadeInTime){
|
||||
game->view.DrawPartialRotatedDecal(pos,GetFrame().GetSourceImage()->Decal(),rotation,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,size,{col.r,col.g,col.b,uint8_t(fadein/original_fadeInTime*col.a)});
|
||||
}else
|
||||
if(fadeout==0){
|
||||
game->view.DrawPartialRotatedDecal(pos,GetFrame().GetSourceImage()->Decal(),rotation,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,size,{col.r,col.g,col.b,uint8_t(fadeout/original_fadeOutTime*col.a)});
|
||||
}
|
||||
game->SetDecalMode(DecalMode::NORMAL);
|
||||
}
|
||||
|
@ -54,6 +54,7 @@ struct Effect{
|
||||
vf2d pos={0,0};
|
||||
float lifetime=0;
|
||||
float fadeout=0;
|
||||
float fadein=0;
|
||||
vf2d size={1,1};
|
||||
Pixel col=WHITE;
|
||||
vf2d spd={};
|
||||
@ -65,18 +66,21 @@ private:
|
||||
public:
|
||||
Effect(vf2d pos,float lifetime,std::string imgFile,bool upperLevel,float size=1.0f,float fadeout=0.0f,vf2d spd={},Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false);
|
||||
Effect(vf2d pos,float lifetime,std::string imgFile,bool upperLevel,vf2d size={1,1},float fadeout=0.0f,vf2d spd={},Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false);
|
||||
Effect(vf2d pos,float lifetime,std::string imgFile,bool upperLevel,float fadein,float fadeout,vf2d size,vf2d spd,Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false);
|
||||
virtual bool Update(float fElapsedTime);
|
||||
Animate2D::Frame GetFrame()const;
|
||||
virtual void Draw()const;
|
||||
bool OnUpperLevel();
|
||||
const EffectType GetType()const;
|
||||
protected:
|
||||
float original_fadeoutTime;
|
||||
float original_fadeOutTime;
|
||||
float original_fadeInTime;
|
||||
EffectType type{EffectType::NONE};
|
||||
private:
|
||||
Animate2D::Animation<std::string>animation;
|
||||
Animate2D::AnimationState internal_animState;
|
||||
bool upperLevel=false;
|
||||
double aliveTime{};
|
||||
};
|
||||
|
||||
struct Meteor:Effect{
|
||||
|
@ -52,7 +52,7 @@ void ForegroundEffect::Draw()const{
|
||||
if(fadeout==0){
|
||||
game->DrawPartialRotatedDecal(pos,GetFrame().GetSourceImage()->Decal(),rotation,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,size,col);
|
||||
} else {
|
||||
game->DrawPartialRotatedDecal(pos,GetFrame().GetSourceImage()->Decal(),rotation,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,size,{col.r,col.g,col.b,uint8_t(fadeout/original_fadeoutTime*255)});
|
||||
game->DrawPartialRotatedDecal(pos,GetFrame().GetSourceImage()->Decal(),rotation,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,size,{col.r,col.g,col.b,uint8_t(fadeout/original_fadeOutTime*255)});
|
||||
}
|
||||
game->SetDecalMode(DecalMode::NORMAL);
|
||||
}
|
@ -81,5 +81,5 @@ void Meteor::Draw()const{
|
||||
if(lifetime<=0){
|
||||
meteorOffset=pos-vf2d{0,GetFrame().GetSourceRect().size.y/4.f}*size;
|
||||
}
|
||||
game->view.DrawPartialRotatedDecal(meteorOffset,GetFrame().GetSourceImage()->Decal(),rotation,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,size,{col.r,col.g,col.b,uint8_t(fadeout/original_fadeoutTime*255)});
|
||||
game->view.DrawPartialRotatedDecal(meteorOffset,GetFrame().GetSourceImage()->Decal(),rotation,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,size,{col.r,col.g,col.b,uint8_t(fadeout/original_fadeOutTime*255)});
|
||||
}
|
@ -473,23 +473,23 @@ void Monster::Draw()const{
|
||||
}
|
||||
|
||||
#pragma region Render Trapper Marked Targets
|
||||
const uint8_t markStackCount{GetMarkStacks()};
|
||||
if(markStackCount>0){
|
||||
float markRotation{-util::lerp(0.f,10.f,markApplicationTimer/0.5f)*sin(PI*markApplicationTimer)};
|
||||
vf2d markScale{vf2d{}.lerp(vf2d{GetSizeMult(),GetSizeMult()},(0.5f-markApplicationTimer)/0.5f)};
|
||||
const Animate2D::Frame&markImg{ANIMATION_DATA["target.png"].GetFrame(game->GetRunTime())};
|
||||
Pixel markCol{markStackCount>1?WHITE:RED};
|
||||
const std::vector<Buff>&buffList{GetBuffs(BuffType::TRAPPER_MARK)};
|
||||
float remainingStackDuration{};
|
||||
for(const Buff&b:buffList){
|
||||
if(b.type==BuffType::TRAPPER_MARK){
|
||||
remainingStackDuration=b.duration;
|
||||
break;
|
||||
const uint8_t markStackCount{GetMarkStacks()};
|
||||
if(markStackCount>0){
|
||||
float markRotation{-util::lerp(0.f,10.f,markApplicationTimer/0.5f)*sin(PI*markApplicationTimer)};
|
||||
vf2d markScale{vf2d{}.lerp(vf2d{GetSizeMult(),GetSizeMult()},(0.5f-markApplicationTimer)/0.5f)};
|
||||
const Animate2D::Frame&markImg{ANIMATION_DATA["target.png"].GetFrame(game->GetRunTime())};
|
||||
Pixel markCol{markStackCount>1?WHITE:RED};
|
||||
const std::vector<Buff>&buffList{GetBuffs(BuffType::TRAPPER_MARK)};
|
||||
float remainingStackDuration{};
|
||||
for(const Buff&b:buffList){
|
||||
if(b.type==BuffType::TRAPPER_MARK){
|
||||
remainingStackDuration=b.duration;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(remainingStackDuration<1.f)markCol.a*=remainingStackDuration;
|
||||
game->view.DrawPartialRotatedDecal(drawPos,markImg.GetSourceImage()->Decal(),markRotation,markImg.GetSourceRect().size/2.f,markImg.GetSourceRect().pos,markImg.GetSourceRect().size,markScale,markCol);
|
||||
}
|
||||
if(remainingStackDuration<1.f)markCol.a*=remainingStackDuration;
|
||||
game->view.DrawPartialRotatedDecal(drawPos,markImg.GetSourceImage()->Decal(),markRotation,markImg.GetSourceRect().size/2.f,markImg.GetSourceRect().pos,markImg.GetSourceRect().size,markScale,markCol);
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
if(GameSettings::TerrainCollisionBoxesEnabled()&&IsSolid()&&solidFadeTimer>0.f){
|
||||
@ -640,7 +640,7 @@ bool Monster::_Hurt(int damage,bool onUpperLevel,float z,const TrueDamageFlag da
|
||||
const bool NormalDamageCalculationRequired{!IsDOT&&!TrueDamage};
|
||||
const bool PlayHitSoundEffect{!IsDOT};
|
||||
|
||||
if(!TrueDamage&&!IsDOT&&(Invulnerable()||!IsAlive()||onUpperLevel!=OnUpperLevel()||AttackAvoided(z)))return false;
|
||||
if(!TrueDamage&&!IsDOT&&InUndamageableState(onUpperLevel,z))return false;
|
||||
if(game->InBossEncounter()){
|
||||
game->StartBossEncounter();
|
||||
}
|
||||
@ -674,6 +674,7 @@ bool Monster::_Hurt(int damage,bool onUpperLevel,float z,const TrueDamageFlag da
|
||||
dotNumberPtr.get()->RecalculateSize();
|
||||
}else{
|
||||
dotNumberPtr=std::make_shared<DamageNumber>(pos-vf2d{0,GetCollisionRadius()/2.f},int(mod_dmg),false,DamageNumberType::DOT);
|
||||
dotNumberPtr->riseSpd=dotNumberPtr->originalRiseSpd=-10.f;
|
||||
DAMAGENUMBER_LIST.push_back(dotNumberPtr);
|
||||
}
|
||||
lastDotTimer=0.05f;
|
||||
@ -1260,4 +1261,38 @@ void Monster::ApplyMark(float time,uint8_t stackCount){
|
||||
}
|
||||
}else AddBuff(BuffType::TRAPPER_MARK,time,stackCount);
|
||||
markApplicationTimer=0.5f;
|
||||
}
|
||||
|
||||
std::optional<Monster*>Monster::GetNearestMonster(const vf2d point,const float maxDistance,const bool onUpperLevel,const float z){
|
||||
std::optional<Monster*>closestMonster;
|
||||
std::optional<Monster*>closestGenericMonster;
|
||||
for(std::unique_ptr<Monster>&m:MONSTER_LIST){
|
||||
geom2d::line<float>aimingLine=geom2d::line<float>(point,m->GetPos());
|
||||
float distToMonster=aimingLine.length();
|
||||
float distToClosestPoint,distToClosestGenericPoint;
|
||||
if(closestMonster.has_value())distToClosestPoint=geom2d::line<float>(point,closestMonster.value()->GetPos()).length();
|
||||
else distToClosestPoint=std::numeric_limits<float>::max();
|
||||
if(closestGenericMonster.has_value())distToClosestGenericPoint=geom2d::line<float>(point,closestGenericMonster.value()->GetPos()).length();
|
||||
else distToClosestGenericPoint=std::numeric_limits<float>::max();
|
||||
if(!m->InUndamageableState(onUpperLevel,z)){
|
||||
if(distToClosestPoint>distToMonster&&distToMonster<=maxDistance){
|
||||
closestMonster=&*m;
|
||||
}
|
||||
}
|
||||
if(m->IsAlive()&&distToClosestGenericPoint>distToMonster&&distToMonster<=maxDistance){
|
||||
closestGenericMonster=&*m;
|
||||
}
|
||||
}
|
||||
if(closestMonster.has_value()){
|
||||
return closestMonster;
|
||||
}else
|
||||
if(closestGenericMonster.has_value()){
|
||||
return closestGenericMonster;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
const bool Monster::InUndamageableState(const bool onUpperLevel,const float z)const{
|
||||
return Invulnerable()||!IsAlive()||onUpperLevel!=OnUpperLevel()||AttackAvoided(z);
|
||||
}
|
@ -202,6 +202,9 @@ public:
|
||||
const uint8_t GetMarkStacks()const; //Number of Trapper marks on this target.
|
||||
void TriggerMark(); //Deals no damage, but causes a mark proc to occur.
|
||||
void ApplyMark(float time,uint8_t stackCount); //Adds stackCount mark stacks to the target, refreshing the buff to time time.
|
||||
//Gets the nearest target that can be immediately targeted
|
||||
static std::optional<Monster*>GetNearestMonster(const vf2d point,const float maxDistance,const bool onUpperLevel,const float z);
|
||||
const bool InUndamageableState(const bool onUpperLevel,const float z)const;
|
||||
private:
|
||||
//NOTE: Marking a monster for deletion does not trigger any death events. It just simply removes the monster from the field!!
|
||||
// The way this works is that monsters marked for deletion will cause the monster update loop to detect there's at least one or more monsters that must be deleted and will call erase_if on the list at the end of the iteration loop.
|
||||
|
@ -1575,33 +1575,45 @@ const vf2d Player::GetAimingLocation(bool useWalkDir,bool invert){
|
||||
if(xAxis!=0.f||yAxis!=0.f){
|
||||
return {(game->ScreenWidth()*xAxis)/2+game->ScreenWidth()/2,(game->ScreenHeight()*yAxis)/2+game->ScreenHeight()/2};
|
||||
}else{
|
||||
|
||||
if(useWalkDir&&movementVelocity!=vf2d{0,0}){
|
||||
xAxis=aimingAngle.cart().x;
|
||||
yAxis=aimingAngle.cart().y;
|
||||
}
|
||||
|
||||
const vf2d MAX{std::numeric_limits<float>::max(),std::numeric_limits<float>::max()};
|
||||
|
||||
if(xAxis!=0.f||yAxis!=0.f){
|
||||
return {(game->ScreenWidth()*xAxis)/2+game->ScreenWidth()/2,(game->ScreenHeight()*yAxis)/2+game->ScreenHeight()/2};
|
||||
}else{
|
||||
//Find the closest monster target.
|
||||
vf2d closestPoint={std::numeric_limits<float>::max(),std::numeric_limits<float>::max()};
|
||||
//Find the closest monster target. Provide a "Generic" target in case a target that is invulnerable is the only target that is available (and alive).
|
||||
std::optional<vf2d>closestPoint;
|
||||
std::optional<vf2d>closestGenericPoint; //Even if the monster is invulnerable, it might be worth targeting if a normal target is not found.
|
||||
for(std::unique_ptr<Monster>&m:MONSTER_LIST){
|
||||
if(m->IsAlive()&&!m->Invulnerable()){
|
||||
geom2d::line<float>aimingLine=geom2d::line<float>(GetPos(),m->GetPos());
|
||||
float distToMonster=aimingLine.length();
|
||||
float distToClosestPoint=geom2d::line<float>(GetPos(),closestPoint).length();
|
||||
geom2d::line<float>aimingLine=geom2d::line<float>(GetPos(),m->GetPos());
|
||||
float distToMonster=aimingLine.length();
|
||||
float distToClosestPoint=geom2d::line<float>(GetPos(),closestPoint.value_or(MAX)).length();
|
||||
float distToClosestGenericPoint=geom2d::line<float>(GetPos(),closestGenericPoint.value_or(MAX)).length();
|
||||
if(!m->InUndamageableState(OnUpperLevel(),GetZ())){
|
||||
if(distToClosestPoint>distToMonster&&distToMonster<=operator""_Pixels("Player.Auto Aim Detection Distance"_F)){
|
||||
closestPoint=m->GetPos();
|
||||
}
|
||||
}
|
||||
if(m->IsAlive()&&distToClosestGenericPoint>distToMonster&&distToMonster<=operator""_Pixels("Player.Auto Aim Detection Distance"_F)){
|
||||
closestGenericPoint=m->GetPos();
|
||||
}
|
||||
}
|
||||
if(closestPoint!=vf2d{std::numeric_limits<float>::max(),std::numeric_limits<float>::max()}){
|
||||
geom2d::line<float>aimingLine=geom2d::line<float>(GetPos(),closestPoint);
|
||||
vf2d aimingPoint=aimingLine.rpoint(invert?(-operator""_Pixels("Player.Aiming Cursor Max Distance"_F)):std::min(aimingLine.length()+24.f,float(operator""_Pixels("Player.Aiming Cursor Max Distance"_F))));
|
||||
return game->GetScreenSize()/2+aimingPoint-GetPos();
|
||||
std::optional<geom2d::line<float>>aimingLine;
|
||||
if(closestPoint.has_value()){
|
||||
aimingLine=geom2d::line<float>(GetPos(),closestPoint.value());
|
||||
}else
|
||||
return game->GetScreenSize()/2+vf2d{float(operator""_Pixels("Player.Aiming Cursor Max Distance"_F)),aimingAngle.y}.cart();
|
||||
if(closestGenericPoint.has_value()){
|
||||
aimingLine=geom2d::line<float>(GetPos(),closestGenericPoint.value());
|
||||
}
|
||||
|
||||
if(aimingLine.has_value()){
|
||||
vf2d aimingPoint=aimingLine.value().rpoint(invert?(-operator""_Pixels("Player.Aiming Cursor Max Distance"_F)):std::min(aimingLine.value().length()+24.f,float(operator""_Pixels("Player.Aiming Cursor Max Distance"_F))));
|
||||
return game->GetScreenSize()/2+aimingPoint-GetPos();
|
||||
}else return game->GetScreenSize()/2+vf2d{float(operator""_Pixels("Player.Aiming Cursor Max Distance"_F)),aimingAngle.y}.cart();
|
||||
}
|
||||
}
|
||||
}else{
|
||||
|
@ -98,6 +98,6 @@ void PulsatingFire::Draw()const{
|
||||
effectSpr=&ANIMATION_DATA["fire_ring0.png"];
|
||||
}
|
||||
const Renderable*img=effectSpr->GetFrame(0).GetSourceImage();
|
||||
game->view.DrawPartialDecal(pos-effectSpr->GetFrame(0).GetSourceRect().size/2*size,img->Decal(),effectSpr->GetFrame(0).GetSourceRect().pos,effectSpr->GetFrame(0).GetSourceRect().size,size,{255,uint8_t(pulsatingFireValues[i]*256),0,uint8_t((63*(sin("Wizard.Ability 3.FireRingOscillatingFrequency"_F*lifetime+PI*pulsatingFireValues[i]))+63)*(fadeout/original_fadeoutTime))});
|
||||
game->view.DrawPartialDecal(pos-effectSpr->GetFrame(0).GetSourceRect().size/2*size,img->Decal(),effectSpr->GetFrame(0).GetSourceRect().pos,effectSpr->GetFrame(0).GetSourceRect().size,size,{255,uint8_t(pulsatingFireValues[i]*256),0,uint8_t((63*(sin("Wizard.Ability 3.FireRingOscillatingFrequency"_F*lifetime+PI*pulsatingFireValues[i]))+63)*(fadeout/original_fadeOutTime))});
|
||||
}
|
||||
}
|
@ -96,7 +96,19 @@ void Trapper::InitializeClassAbilities(){
|
||||
#pragma region Trapper Ability 1 (Mark Target)
|
||||
Trapper::ability1.action=
|
||||
[](Player*p,vf2d pos={}){
|
||||
|
||||
std::optional<Monster*>nearestMonster{Monster::GetNearestMonster(pos,Trapper::ability1.precastInfo.range,p->OnUpperLevel(),p->GetZ())};
|
||||
vf2d targetPos{pos};
|
||||
if(nearestMonster.has_value()){
|
||||
targetPos=nearestMonster.value()->GetPos();
|
||||
nearestMonster.value()->ApplyMark("Trapper.Ability 1.Duration"_F,"Trapper.Ability 1.Stack Count"_I);
|
||||
}
|
||||
for(int i:std::ranges::iota_view(0,int(util::distance(p->GetPos(),targetPos)/16))){
|
||||
float drawDist{i*16.f};
|
||||
float fadeInTime{i*0.05f};
|
||||
float fadeOutTime{0.5f+i*0.05f};
|
||||
float effectSize{util::random(0.4f)};
|
||||
game->AddEffect(std::make_unique<Effect>(geom2d::line<float>(p->GetPos(),targetPos).rpoint(drawDist),0.f,"mark_trail.png",p->OnUpperLevel(),fadeInTime,fadeOutTime,vf2d{effectSize,effectSize},vf2d{},Pixel{255,255,255,uint8_t(util::random_range(60,150))},0.f,0.f,true),true);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
#pragma endregion
|
||||
|
@ -39,7 +39,7 @@ All rights reserved.
|
||||
#define VERSION_MAJOR 1
|
||||
#define VERSION_MINOR 2
|
||||
#define VERSION_PATCH 3
|
||||
#define VERSION_BUILD 10264
|
||||
#define VERSION_BUILD 10275
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
@ -59,7 +59,7 @@ Trapper
|
||||
CancelCast = 0
|
||||
|
||||
Duration = 7s
|
||||
Hit Count = 5
|
||||
Stack Count = 5
|
||||
Damage Increase Bonus = 60%
|
||||
|
||||
#RGB Values. Color 1 is the circle at full cooldown, Color 2 is the color at empty cooldown.
|
||||
|
@ -110,6 +110,7 @@ Images
|
||||
GFX_Dagger = dagger.png
|
||||
GFX_Shine = shine.png
|
||||
GFX_TargetMark = target.png
|
||||
GFX_MarkTrail = mark_trail.png
|
||||
|
||||
GFX_Thief_Sheet = nico-thief.png
|
||||
GFX_Trapper_Sheet = nico-trapper.png
|
||||
|
Binary file not shown.
BIN
Adventures in Lestoria/assets/mark_trail.png
Normal file
BIN
Adventures in Lestoria/assets/mark_trail.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 941 B |
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user