Display item loadout HUD information while playing. Fix item drops bugging out at lower frame rates.

pull/28/head
sigonasr2 1 year ago
parent 633c9355bc
commit 3605aa818d
  1. 70
      Crawler/Crawler.cpp
  2. 3
      Crawler/Crawler.h
  3. 5
      Crawler/Item.cpp
  4. 1
      Crawler/Item.h
  5. 5
      Crawler/ItemDrop.cpp
  6. 2
      Crawler/Version.h
  7. 2
      Crawler/assets/config/configuration.txt
  8. 94
      Crawler/assets/config/items/ItemDatabase.txt
  9. 2
      Crawler/assets/config/items/items.txt

@ -1189,23 +1189,36 @@ void Crawler::RenderCooldowns(){
player->GetAbility4(), player->GetAbility4(),
}; };
const auto DrawCooldown=[&](vf2d pos,Ability&a){ const auto DrawCooldown=[&](vf2d pos,Ability&a,int loadoutSlot=-1/*Set to 0-2 to get an item slot rendered instead*/){
bool circle=loadoutSlot==-1;
if(a.name!="???"){ if(a.name!="???"){
if(a.cooldown>0.1){ if(a.cooldown>0.1){
DrawDecal(pos,GFX[a.icon].Decal(),{1,1},{255,255,255,64}); vf2d iconScale={1,1};
DrawPie(pos+vf2d{12,12},12,360-(a.cooldown/a.COOLDOWN_TIME)*360,PixelLerp(a.barColor1,a.barColor2,(a.cooldown/a.COOLDOWN_TIME))); if(loadoutSlot!=-1)iconScale={0.7,0.7};
DrawRotatedDecal(pos+vf2d{12,12},GFX[a.icon].Decal(),0,{12,12},iconScale,{255,255,255,64});
if(circle){
DrawPie(pos+vf2d{12,12},12,360-(a.cooldown/a.COOLDOWN_TIME)*360,PixelLerp(a.barColor1,a.barColor2,(a.cooldown/a.COOLDOWN_TIME)));
}else{
DrawSquarePie(pos+vf2d{12,12},10,360-(a.cooldown/a.COOLDOWN_TIME)*360,PixelLerp(a.barColor1,a.barColor2,(a.cooldown/a.COOLDOWN_TIME)));
}
std::stringstream cooldownTimeDisplay; std::stringstream cooldownTimeDisplay;
cooldownTimeDisplay<<std::fixed<<std::setprecision(1)<<a.cooldown; cooldownTimeDisplay<<std::fixed<<std::setprecision(1)<<a.cooldown;
DrawShadowStringPropDecal(pos+vf2d{12,12}-vf2d{float(GetTextSizeProp(cooldownTimeDisplay.str()).x*0.5),float(GetTextSizeProp(cooldownTimeDisplay.str()).y*1)}/2,cooldownTimeDisplay.str(),WHITE,BLACK,{0.5,1}); DrawShadowStringPropDecal(pos+vf2d{12,12}-vf2d{float(GetTextSizeProp(cooldownTimeDisplay.str()).x*0.5),float(GetTextSizeProp(cooldownTimeDisplay.str()).y*1)}/2,cooldownTimeDisplay.str(),WHITE,BLACK,{0.5,1});
}else{ }else{
DrawDecal(pos,GFX[a.icon].Decal(),{1,1},WHITE); vf2d iconScale={1,1};
if(loadoutSlot!=-1)iconScale={0.7,0.7};
DrawRotatedDecal(pos+vf2d{12,12},GFX[a.icon].Decal(),0,{12,12},iconScale,WHITE);
} }
DrawDecal(pos,GFX["skill_overlay_icon.png"].Decal()); Decal*overlayIcon=GFX["skill_overlay_icon.png"].Decal();
if(!circle)overlayIcon=GFX["square_skill_overlay_icon.png"].Decal();
DrawDecal(pos,overlayIcon);
Pixel shortNameCol=BLUE,manaCostShadowCol=DARK_BLUE,keyDisplayCol=YELLOW; Pixel shortNameCol=BLUE,manaCostShadowCol=DARK_BLUE,keyDisplayCol=YELLOW;
if(player->GetMana()<a.manaCost){ if(player->GetMana()<a.manaCost){
DrawDecal(pos,GFX["skill_overlay_icon_overlay.png"].Decal(),{1,1},DARK_RED); Decal*overlayOverlayIcon=GFX["skill_overlay_icon_overlay.png"].Decal();
if(!circle)overlayOverlayIcon=GFX["square_skill_overlay_icon_empty.png"].Decal();
DrawDecal(pos,overlayOverlayIcon,{1,1},DARK_RED);
shortNameCol=RED; shortNameCol=RED;
manaCostShadowCol=DARK_RED; manaCostShadowCol=DARK_RED;
keyDisplayCol=RED; keyDisplayCol=RED;
@ -1216,6 +1229,20 @@ void Crawler::RenderCooldowns(){
keyDisplayCol=GREY; keyDisplayCol=GREY;
} }
if(loadoutSlot!=-1){
uint32_t itemAmt=GetLoadoutItem(loadoutSlot).Amt();
if(itemAmt>0){
std::string amtString="x"+std::to_string(itemAmt);
vf2d qtySize=vf2d{GetTextSize(amtString)}*vf2d{0.5,0.75};
DrawShadowStringDecal(pos+vf2d{20,20}-qtySize/2,amtString,WHITE,BLACK,{0.5,0.75});
}else{
DrawDecal(pos,GFX["square_skill_overlay_icon_empty.png"].Decal(),{1,1},DARK_RED);
shortNameCol=RED;
manaCostShadowCol=DARK_RED;
keyDisplayCol=RED;
}
}
if(a.manaCost>0){ if(a.manaCost>0){
vf2d manaCostSize=vf2d{GetTextSize(std::to_string(a.manaCost))}*vf2d{0.5,0.75}; vf2d manaCostSize=vf2d{GetTextSize(std::to_string(a.manaCost))}*vf2d{0.5,0.75};
DrawShadowStringDecal(pos+vf2d{20,4}-manaCostSize/2,std::to_string(a.manaCost),{192,192,255},manaCostShadowCol,{0.5,0.75}); DrawShadowStringDecal(pos+vf2d{20,4}-manaCostSize/2,std::to_string(a.manaCost),{192,192,255},manaCostShadowCol,{0.5,0.75});
@ -1238,6 +1265,15 @@ void Crawler::RenderCooldowns(){
} }
DrawCooldown({float(ScreenWidth()-32),float(ScreenHeight()-32)},player->GetRightClickAbility()); DrawCooldown({float(ScreenWidth()-32),float(ScreenHeight()-32)},player->GetRightClickAbility());
for(int i=-1;i<2;i++){
int loadoutSlot=i+1;//0-2
Ability*a=&GetPlayer()->useItem1;
if(loadoutSlot==1){a=&GetPlayer()->useItem2;}else
if(loadoutSlot==2){a=&GetPlayer()->useItem3;}
DrawCooldown({float(ScreenWidth()/2+i*26-12),float(ScreenHeight()-26)},*a,loadoutSlot);
}
} }
void Crawler::AddEffect(std::unique_ptr<Effect>foreground,std::unique_ptr<Effect> background){ void Crawler::AddEffect(std::unique_ptr<Effect>foreground,std::unique_ptr<Effect> background){
@ -1590,6 +1626,9 @@ std::map<std::string,std::vector<ZoneData>>&Crawler::GetZoneData(MapName map){
} }
void Crawler::ChangePlayerClass(Class cl){ void Crawler::ChangePlayerClass(Class cl){
Ability itemAbility1=player->useItem1;
Ability itemAbility2=player->useItem2;
Ability itemAbility3=player->useItem3;
switch(cl){ switch(cl){
case WARRIOR:{ case WARRIOR:{
player.reset(NEW Warrior(player.get())); player.reset(NEW Warrior(player.get()));
@ -1616,6 +1655,9 @@ void Crawler::ChangePlayerClass(Class cl){
player->atkGrowthRate=DATA.GetProperty(player->GetClassName()+".AtkGrowthRate").GetReal(); player->atkGrowthRate=DATA.GetProperty(player->GetClassName()+".AtkGrowthRate").GetReal();
sig::Animation::SetupPlayerAnimations(); sig::Animation::SetupPlayerAnimations();
GetPlayer()->UpdateIdleAnimation(DOWN); GetPlayer()->UpdateIdleAnimation(DOWN);
GetPlayer()->SetItem1UseFunc(itemAbility1);
GetPlayer()->SetItem2UseFunc(itemAbility2);
GetPlayer()->SetItem3UseFunc(itemAbility3);
camera.SetTarget(player->GetPos()); camera.SetTarget(player->GetPos());
} }
@ -2054,27 +2096,24 @@ void Crawler::SetLoadoutItem(int slot,std::string itemName){
inputGroup=&Player::KEY_ITEM3; inputGroup=&Player::KEY_ITEM3;
}break; }break;
} }
Ability itemAbility{itemName,"","","Item.Item Cooldown Time"_F,0,inputGroup,"items/"+itemName,VERY_DARK_RED,DARK_RED,PrecastData{GetLoadoutItem(slot).CastTime(),0,0},true}; Ability itemAbility{itemName,"","","Item.Item Cooldown Time"_F,0,inputGroup,"items/"+itemName+".png",VERY_DARK_RED,DARK_RED,PrecastData{GetLoadoutItem(slot).CastTime(),0,0},true};
switch(slot){ switch(slot){
case 0:{ case 0:{
itemAbility.action=[&](Player*p,vf2d pos={}){ itemAbility.action=[&](Player*p,vf2d pos={}){
game->UseLoadoutItem(0); return game->UseLoadoutItem(0);
return true;
}; };
game->GetPlayer()->SetItem1UseFunc(itemAbility); game->GetPlayer()->SetItem1UseFunc(itemAbility);
}break; }break;
case 1:{ case 1:{
itemAbility.action=[&](Player*p,vf2d pos={}){ itemAbility.action=[&](Player*p,vf2d pos={}){
game->UseLoadoutItem(1); return game->UseLoadoutItem(1);
return true;
}; };
game->GetPlayer()->SetItem2UseFunc(itemAbility); game->GetPlayer()->SetItem2UseFunc(itemAbility);
}break; }break;
case 2:{ case 2:{
itemAbility.action=[&](Player*p,vf2d pos={}){ itemAbility.action=[&](Player*p,vf2d pos={}){
game->UseLoadoutItem(2); return game->UseLoadoutItem(2);
return true;
}; };
game->GetPlayer()->SetItem3UseFunc(itemAbility); game->GetPlayer()->SetItem3UseFunc(itemAbility);
}break; }break;
@ -2085,14 +2124,15 @@ void Crawler::SetLoadoutItem(int slot,std::string itemName){
} }
} }
void Crawler::UseLoadoutItem(int slot){ bool Crawler::UseLoadoutItem(int slot){
if(slot<0||slot>loadout.size()-1)ERR("Invalid inventory slot "+std::to_string(slot)+", please choose a slot in range (0-"+std::to_string(loadout.size()-1)+")."); if(slot<0||slot>loadout.size()-1)ERR("Invalid inventory slot "+std::to_string(slot)+", please choose a slot in range (0-"+std::to_string(loadout.size()-1)+").");
if(GetLoadoutItem(slot).Amt()>0){ if(GetLoadoutItem(slot).Amt()>0){
Inventory::UseItem(loadout[slot].Name()); Inventory::UseItem(loadout[slot].Name());
GetLoadoutItem(slot).OnUseAction(); GetLoadoutItem(slot).OnUseAction();
GetLoadoutItem(slot).amt--; GetLoadoutItem(slot).amt--;
return true;
} }
olc_UpdateKeyState(K1,false); return false;
} }
void Crawler::ClearLoadoutItem(int slot){ void Crawler::ClearLoadoutItem(int slot){

@ -178,7 +178,8 @@ public:
void SetChapter(int chapter); void SetChapter(int chapter);
Item&GetLoadoutItem(int slot); Item&GetLoadoutItem(int slot);
void SetLoadoutItem(int slot,std::string itemName); void SetLoadoutItem(int slot,std::string itemName);
void UseLoadoutItem(int slot); //Returns true if the item can be used (we have >0 of it)
bool UseLoadoutItem(int slot);
//Blanks out this loadout item. //Blanks out this loadout item.
void ClearLoadoutItem(int slot); void ClearLoadoutItem(int slot);

@ -375,6 +375,7 @@ void ItemOverlay::Draw(){
void ItemOverlay::AddToItemOverlay(const ItemInfo&it){ void ItemOverlay::AddToItemOverlay(const ItemInfo&it){
items.push_back(ItemOverlay{it}); items.push_back(ItemOverlay{it});
std::for_each(items.begin(),items.end(),[](ItemOverlay&it){it.ResetTimer();});
} }
float ItemInfo::CastTime(){ float ItemInfo::CastTime(){
@ -385,6 +386,10 @@ float ItemInfo::CooldownTime(){
return cooldownTime; return cooldownTime;
} }
void ItemOverlay::ResetTimer(){
timer=0;
}
float Item::CastTime(){ float Item::CastTime(){
return it->CastTime(); return it->CastTime();
} }

@ -153,4 +153,5 @@ public:
static void AddToItemOverlay(const ItemInfo&it); static void AddToItemOverlay(const ItemInfo&it);
static void Update(); static void Update();
static void Draw(); static void Draw();
void ResetTimer();
}; };

@ -100,11 +100,12 @@ void ItemDrop::UpdateDrops(float fElapsedTime){
float dist=lineTo.length(); float dist=lineTo.length();
if(dist<="ItemDrop.Item Drop Suction Range"_F){ if(dist<="ItemDrop.Item Drop Suction Range"_F){
vf2d pointVel=lineTo.vector().norm(); vf2d pointVel=lineTo.vector().norm();
if((1.f/dist)*200*fElapsedTime>dist){ float moveDistance=(1.f/std::min(48.f,dist))*"ItemDrop.Item Drop Suction Strength"_F*fElapsedTime;
if(moveDistance>dist){
drop.pos=game->GetPlayer()->GetPos(); drop.pos=game->GetPlayer()->GetPos();
drop.collected=true; drop.collected=true;
}else{ }else{
drop.pos+=pointVel*(1.f/std::min(48.f,dist))*"ItemDrop.Item Drop Suction Strength"_F*fElapsedTime; drop.pos+=pointVel*moveDistance;
} }
} }
} }

@ -35,7 +35,7 @@ SUCH DAMAGE.
#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 3109 #define VERSION_BUILD 3127
#define stringify(a) stringify_(a) #define stringify(a) stringify_(a)
#define stringify_(a) #a #define stringify_(a) #a

@ -55,7 +55,7 @@ debug_access_options = 0
debug_map_load_info = 0 debug_map_load_info = 0
# Shows extra info about the player on the HUD # Shows extra info about the player on the HUD
debug_player_info = 1 debug_player_info = 0
# Shows collision boxes of tiles. # Shows collision boxes of tiles.
debug_collision_boxes = 0 debug_collision_boxes = 0

@ -6,7 +6,7 @@ ItemDatabase
Description = Restores 40 health points. Description = Restores 40 health points.
HP Restore = 40 HP Restore = 40
ItemCategory = Consumables ItemCategory = Consumables
Cooldown Time = 2.5 Cooldown Time = 5.0
Cast Time = 0.0 Cast Time = 0.0
} }
Medium Health Potion Medium Health Potion
@ -15,7 +15,7 @@ ItemDatabase
Description = Restores 100 health points. Description = Restores 100 health points.
HP Restore = 100 HP Restore = 100
ItemCategory = Consumables ItemCategory = Consumables
Cooldown Time = 2.5 Cooldown Time = 5.0
Cast Time = 0.0 Cast Time = 0.0
} }
Large Health Potion Large Health Potion
@ -24,7 +24,7 @@ ItemDatabase
Description = Restores 320 health points. Description = Restores 320 health points.
HP Restore = 320 HP Restore = 320
ItemCategory = Consumables ItemCategory = Consumables
Cooldown Time = 2.5 Cooldown Time = 5.0
Cast Time = 0.0 Cast Time = 0.0
} }
Small Mana Potion Small Mana Potion
@ -33,7 +33,7 @@ ItemDatabase
Description = Restores 40 mana points. Description = Restores 40 mana points.
MP Restore = 40 MP Restore = 40
ItemCategory = Consumables ItemCategory = Consumables
Cooldown Time = 2.5 Cooldown Time = 5.0
Cast Time = 0.0 Cast Time = 0.0
} }
Medium Mana Potion Medium Mana Potion
@ -42,7 +42,7 @@ ItemDatabase
Description = Restores 100 mana points. Description = Restores 100 mana points.
MP Restore = 100 MP Restore = 100
ItemCategory = Consumables ItemCategory = Consumables
Cooldown Time = 2.5 Cooldown Time = 5.0
Cast Time = 0.0 Cast Time = 0.0
} }
Large Mana Potion Large Mana Potion
@ -51,147 +51,187 @@ ItemDatabase
Description = Restores 320 mana points. Description = Restores 320 mana points.
MP Restore = 320 MP Restore = 320
ItemCategory = Consumables ItemCategory = Consumables
Cooldown Time = 2.5 Cooldown Time = 5.0
Cast Time = 0.0 Cast Time = 0.0
} }
Dummy Item 1 Dummy Item 1
{ {
ItemScript = Restore
HP Restore = 1
Description = Does nothing apparently. Description = Does nothing apparently.
ItemCategory = Consumables ItemCategory = Consumables
Cooldown Time = 2.5 Cooldown Time = 5.0
Cast Time = 0.0 Cast Time = 0.0
} }
Dummy Item 2 Dummy Item 2
{ {
ItemScript = Restore
HP Restore = 1
Description = Does nothing apparently. Description = Does nothing apparently.
ItemCategory = Consumables ItemCategory = Consumables
Cooldown Time = 2.5 Cooldown Time = 5.0
Cast Time = 0.0 Cast Time = 0.0
} }
Dummy Item 3 Dummy Item 3
{ {
ItemScript = Restore
HP Restore = 1
Description = Does nothing apparently. Description = Does nothing apparently.
ItemCategory = Consumables ItemCategory = Consumables
Cooldown Time = 2.5 Cooldown Time = 5.0
Cast Time = 0.0 Cast Time = 0.0
} }
Dummy Item 4 Dummy Item 4
{ {
ItemScript = Restore
HP Restore = 1
Description = Does nothing apparently. Description = Does nothing apparently.
ItemCategory = Consumables ItemCategory = Consumables
Cooldown Time = 2.5 Cooldown Time = 5.0
Cast Time = 0.0 Cast Time = 0.0
} }
Dummy Item 5 Dummy Item 5
{ {
ItemScript = Restore
HP Restore = 1
Description = Does nothing apparently. Description = Does nothing apparently.
ItemCategory = Consumables ItemCategory = Consumables
Cooldown Time = 2.5 Cooldown Time = 5.0
Cast Time = 0.0 Cast Time = 0.0
} }
Dummy Item 6 Dummy Item 6
{ {
ItemScript = Restore
HP Restore = 1
Description = Does nothing apparently. Description = Does nothing apparently.
ItemCategory = Consumables ItemCategory = Consumables
Cooldown Time = 2.5 Cooldown Time = 5.0
Cast Time = 0.0 Cast Time = 0.0
} }
Dummy Item 7 Dummy Item 7
{ {
ItemScript = Restore
HP Restore = 1
Description = Does nothing apparently. Description = Does nothing apparently.
ItemCategory = Consumables ItemCategory = Consumables
Cooldown Time = 2.5 Cooldown Time = 5.0
Cast Time = 0.0 Cast Time = 0.0
} }
Dummy Item 8 Dummy Item 8
{ {
ItemScript = Restore
HP Restore = 1
Description = Does nothing apparently. Description = Does nothing apparently.
ItemCategory = Consumables ItemCategory = Consumables
Cooldown Time = 2.5 Cooldown Time = 5.0
Cast Time = 0.0 Cast Time = 0.0
} }
Dummy Item 9 Dummy Item 9
{ {
ItemScript = Restore
HP Restore = 1
Description = Does nothing apparently. Description = Does nothing apparently.
ItemCategory = Consumables ItemCategory = Consumables
Cooldown Time = 2.5 Cooldown Time = 5.0
Cast Time = 0.0 Cast Time = 0.0
} }
Dummy Item 10 Dummy Item 10
{ {
ItemScript = Restore
HP Restore = 1
Description = Does nothing apparently. Description = Does nothing apparently.
ItemCategory = Consumables ItemCategory = Consumables
Cooldown Time = 2.5 Cooldown Time = 5.0
Cast Time = 0.0 Cast Time = 0.0
} }
Dummy Item 11 Dummy Item 11
{ {
ItemScript = Restore
HP Restore = 1
Description = Does nothing apparently. Description = Does nothing apparently.
ItemCategory = Consumables ItemCategory = Consumables
Cooldown Time = 2.5 Cooldown Time = 5.0
Cast Time = 0.0 Cast Time = 0.0
} }
Dummy Item 12 Dummy Item 12
{ {
ItemScript = Restore
HP Restore = 1
Description = Does nothing apparently. Description = Does nothing apparently.
ItemCategory = Consumables ItemCategory = Consumables
Cooldown Time = 2.5 Cooldown Time = 5.0
Cast Time = 0.0 Cast Time = 0.0
} }
Dummy Item 13 Dummy Item 13
{ {
ItemScript = Restore
HP Restore = 1
Description = Does nothing apparently. Description = Does nothing apparently.
ItemCategory = Consumables ItemCategory = Consumables
Cooldown Time = 2.5 Cooldown Time = 5.0
Cast Time = 0.0 Cast Time = 0.0
} }
Dummy Item 14 Dummy Item 14
{ {
ItemScript = Restore
HP Restore = 1
Description = Does nothing apparently. Description = Does nothing apparently.
ItemCategory = Consumables ItemCategory = Consumables
Cooldown Time = 2.5 Cooldown Time = 5.0
Cast Time = 0.0 Cast Time = 0.0
} }
Dummy Item 15 Dummy Item 15
{ {
ItemScript = Restore
HP Restore = 1
Description = Does nothing apparently. Description = Does nothing apparently.
ItemCategory = Consumables ItemCategory = Consumables
Cooldown Time = 2.5 Cooldown Time = 5.0
Cast Time = 0.0 Cast Time = 0.0
} }
Dummy Item 16 Dummy Item 16
{ {
ItemScript = Restore
HP Restore = 1
Description = Does nothing apparently. Description = Does nothing apparently.
ItemCategory = Consumables ItemCategory = Consumables
Cooldown Time = 2.5 Cooldown Time = 5.0
Cast Time = 0.0 Cast Time = 0.0
} }
Dummy Item 17 Dummy Item 17
{ {
ItemScript = Restore
HP Restore = 1
Description = Does nothing apparently. Description = Does nothing apparently.
ItemCategory = Consumables ItemCategory = Consumables
Cooldown Time = 2.5 Cooldown Time = 5.0
Cast Time = 0.0 Cast Time = 0.0
} }
Dummy Item 18 Dummy Item 18
{ {
ItemScript = Restore
HP Restore = 1
Description = Does nothing apparently. Description = Does nothing apparently.
ItemCategory = Consumables ItemCategory = Consumables
Cooldown Time = 2.5 Cooldown Time = 5.0
Cast Time = 0.0 Cast Time = 0.0
} }
Dummy Item 19 Dummy Item 19
{ {
ItemScript = Restore
HP Restore = 1
Description = Does nothing apparently. Description = Does nothing apparently.
ItemCategory = Consumables ItemCategory = Consumables
Cooldown Time = 2.5 Cooldown Time = 5.0
Cast Time = 0.0 Cast Time = 0.0
} }
Dummy Item 20 Dummy Item 20
{ {
ItemScript = Restore
HP Restore = 1
Description = Does nothing apparently. Description = Does nothing apparently.
ItemCategory = Consumables ItemCategory = Consumables
Cooldown Time = 2.5 Cooldown Time = 5.0
Cast Time = 0.0 Cast Time = 0.0
} }
Bandages Bandages
@ -200,7 +240,7 @@ ItemDatabase
Description = Restores 10% health points. Description = Restores 10% health points.
HP % Restore = 10% HP % Restore = 10%
Cast Time = 1.0 Cast Time = 1.0
Cooldown Time = 2.5 Cooldown Time = 5.0
ItemCategory = Consumables ItemCategory = Consumables
} }
Green Slime Remains Green Slime Remains

@ -7,7 +7,7 @@ ItemConfiguration
Item Item
{ {
# Amount of time to wait before an item can be used again (Global). # Amount of time to wait before an item can be used again (Global).
Item Cooldown Time = 2.5 Item Cooldown Time = 5.0
} }
ItemDrop ItemDrop
{ {

Loading…
Cancel
Save