Action RPG Framework

by Forum_account
Action RPG Framework
A framework for developing action RPGs.
ID:836963
 
i would like it in my game that only rangers can shoot arrows. the problem with the arrow ability is that a ranger can easily stand at a distance from the mob and use as many arrows as needed. i would like to base the arrow ability on the amount of arrows in the inventory. can i have an example on how i could override the arrow ability to use the arrows in inventory?
You'd use the mob's has_item() and consume_item() procs. Both procs take an item type and have an optional second parameter which is the quantity. If you don't specify a quantity, it consumes just one item. This is the ShootArrow definition from the sample game with these checks added. In can_use() you check that they have an arrow and in effect() you consume the arrow.

item
arrow
stack_size = 100

Ability
ShootArrow
name = "Shoot Arrow"
icon_state = "ability-button-shoot-arrow"
description = "Ranged attack that deals 10 damage."
animation = "attacking"
cooldown = 20

// check the cooldown
can_use(mob/user)
if(user.on_cooldown("shoot-arrow", "attack"))
return 0

// the user must have a valid target selected
if(!user.can_attack(user.target))
user.no_target_selected(src)
return 0

// and they have to be within range of their target
if(user.distance_to(user.target) > 200)
user.target_out_of_range(src)
return 0

// and they need line of sight to their target
if(!user.los(user.target))
user.no_line_of_sight(user.target)
return 0

// and they need an arrow in their inventory
if(!user.has_item(/item/arrow))
return 0

return ..()

effect(mob/user)

// 20 tick ability cooldown, 10 tick attack cooldown
user.cooldown("shoot-arrow", cooldown)
user.cooldown("attack", 10)

// consume one arrow
user.consume_item(/item/arrow)

new /missile/ShootArrow(user, user.target)
how about for the next update removing an item from inventory when its stacksize is 0. the iron_bar and arrows don't remove.

ive just been using the remove_item() proc instead of consume_item() and it works fine.
hi D-Cire, yea i can remove an item but the problem is that i don't know in this example where to put the code to remove the item. nevertheless, it would be good if the statesize are removed from the inventory when they reach 0
consume_item() should cause the stack to be deleted when its count reaches zero. If it doesn't, that's a bug and it'll be fixed.
i tested consume_item() with the arrows. it does not delete when 0. this must be a bug. also, when the iron_bars stack is 0, it does not delete from the inventory
Kalster, i mean im not using consume_item(), i use the remove_item() proc, and it deletes the stack for me.
This was caused by a bug in remove_item. Sometimes it'd work, sometimes it wouldn't. Consume_item calls remove_item, so that wouldn't fix it. I'll try to post an update this weekend that'll fix this problem.
yes i misunderstood your post D-Cire.

Forum_account, how about then the user presses the "i" key, in the framework code, it searches for empty stacks and removes the item from the inventory slot before the inventory is displayed?
The empty stacks should be removed by consume_item, this was just a bug. It'll be fixed in the next version.

If you'd like to fix this now, here's the updated proc you can put in player-inventory.dm:

        // returns a list of the instances of the specified quantity of items
remove_item(item_type, quantity = 1)

if(!has_item(item_type, quantity))
return null

var/list/items = list()

for(var/item/item in contents)
if(quantity <= 0)
break

if(item.type != item_type)
continue

// if the item is stackable
if(item.stack_size)

// if we remove the whole stack
if(quantity >= item.count)
quantity -= item.count
items += item
item.loc = null

// if we only need part of the stack
else
// reduce the size of the stack in your inventory
item.count -= quantity

// create the partial stack that's being removed
var/item/stack = new item.type()
stack.loc = null
stack.count = quantity

quantity = 0
items += stack

// non-stackable items count as one each
else
if(quantity > 0)
items += item
item.loc = null
quantity -= 1

if(inventory)
inventory.refresh()

return items
the code below was added to the ability.dm file to get the arrows to work. what i would like to do is add this code to my file. the problem is that every time there is an update, i overwrite this code in the ability.dm file. this code in my file is not working. is there a way to get this arrow code to work outside of the ability.dm file, without copying anything from the ability.dm file?

-----my_file.dm
Ability
ShootArrow

// check the cooldown
can_use(mob/user)

// and they need an arrow in their inventory
if(!user.has_item(/item/arrow))
return 0

effect(mob/user)

user.consume_item(/item/arrow)
In theory you should be able to add the following code in a new file and it will override the function and allow you to retain this functionality throughout updates.

Ability
ShootArrow

// check the cooldown
can_use(mob/user)

// and they need an arrow in their inventory
if(!user.has_item(/item/arrow))
return 0

return ..()

effect(mob/user)
if(user.consume_item(/item/arrow))
return ..()
it works. i will remember to use the ..() statement
The stuff in the demo\ folder isn't really part of the framework, it's just there to show you how to do some things (and to give people something to see/play when they download and run the library). If you want to use something from the demo, the best way is to copy the code into your own project. I try to keep the impact minimal when I make changes to the framework, but when I change the sample game I'm not as careful - if you're relying on that code you might get some unexpected changes.