DoomRL > Modding

Changing the ammo system?

(1/10) > >>

Autoquark:
This is my first real attempt at modding doomRL, so please bear with me if these questions are rather basic.

I'm trying to alter the doomRL ammo system to be like the system in Doom, where the player has a fixed capacity for each kind of ammo. I thought the easiest way to do this might be to change the size that ammo stacks to in the inventory to the amount I want the player to be able to hold, and then only allow the player's inventory to hold one ammo stack of each kind. Would it be possible to do this using the OnPickup hook? If so, should I define my own ammo types and add the hook to them, or just use the general OnPickup hook and the existing ammo types?

Thanks for any help.

tehtmi:
Ammo is maybe the weirdest item type in DoomRL because it is the only thing that stacks.  Ammo stack items are created automatically by the engine to do ammo management, sometimes in unintuitive ways.  Because of this, it won't be easy to implement this kind of system robustly, but here are some approaches you could try.

Hooks on ammo items don't work well in the current version.  OnPickupCheck doesn't seem to be called at all, and OnPickup is called after the ammo is added.  This could probably still be used, but you would have to fix up the ammo in the player's inventory after the fact.  Another thing you can do is use powerups to add ammo to the player's inventory like Game Hunter does in HereticRL.  OnPickupCheck and OnPickup work for powerups and could be used to implement any logic you like.  Either way, you have to worry about other ways that ammo can be created like dropping ammo from the inventory and unloading weapons.  These will probably be hard to handle well.

Yet another approach would be not to use items for ammo at all.  You could add custom properties to the player (or wherever) to track ammo, and again use powerups to add ammo to these counters.  If you go this approach, all your weapons would need to have custom OnFire and OnReload hooks to make use of the custom ammo system, but it is probably doable.  The difficulty I would anticipate here is displaying the ammo to the player.  Probably I would try to add it in to the name of currently equipped weapons using some combination of OnEquip, OnRemove, and OnEquipTick.

Autoquark:
Thanks for the detailed answer. I might leave that idea for a bit, at least until I'm more familiar with the system and lua. I guess I'll add some other random questions:

1. If I'm creating an episode, and I want to define custom items, where should I put the definitions? And which hook is best for adding stuff to the player's starting inventory?

EDIT: Nevermind, after looking at the skulltag arena files, I see that you have to use register_item. I thought that they had to be put inside a function.

2. I was also wondering about creating my own mod items. I guess you use ui.msg_choice to let the player choose an item slot to mod, but I can't find out from the wiki how to reference the player's equipped items. Is there any example code for this?

3. Is there any easy way to prevent the level generator from generating the built-in items, or will I have to wait for total conversion mod support?

Thanks again for helping.

EDIT2: After adding various missing values to my new item which weren't included in the tutorial template, I now get the following error message:

core\\core.lua:221: attempt to index field '?' (a nil value)

Here's my item declaration:


--- Code: ---register_item "new_pulsecannon" {
name = "pulse cannon",
id = "extra_pulsecannon",
desc = "The Microsol Pulse Cannon provides cost-effective firepower thanks to the self-recharging battery.",
ascii = "}" ,
sprite = SPRITE_CHAINGUN,
level = 1,
weight = 1000, --bit of a guess, see item generation page on wiki
flags = {IF_RECHARGE},
firstmsg = "",
color_id = "generic",
--type specific
    type         = ITEMTYPE_RANGED, --required field
damage        = "2d4",           --required field
    damagetype    = DAMAGE_BULLET,   --required field
    group         = "weapon-pistol", --defaults to "weapon-other"
    fire          = 10,              --defaults to 10
    acc           = 0,               --defaults to 0
    radius        = 0,               --defaults to 0 (_RANGED and _NRANGED only)
    shots         = 1,               --defaults to 0
    ammo_id       = "ammo",        --required field (_RANGED only)
    ammomax       = 12,              --required field (_RANGED only)
    reload        = 12,              --defaults to 10 (_RANGED only)
    shotcost      = 1,               --defaults to 0 (_RANGED only). I think 1 makes it a rapid-fire weapon and 0 a single-shot
    altfire       = ALT_AIMED,       --defaults to ALT_NONE (_MELEE and _RANGED only)
    altfirename   = "aimed shot",    --default depends on altfire (_MELEE and _RANGED only)
    altreload     = RELOAD_FULL,     --defaults to RELOAD_NONE (_RANGED only)
    altreloadname = "full",          --default depends on altreload (_RANGED only)
    --soundID       = "pistol",        --defaults to "id" (_RANGED and _NRANGED only)
    missile       = "gun",
psprite   = SPRITE_PLAYER_CHAINGUN --the sprite used to represent the player when equipped
}
--- End code ---

tehtmi:

--- Quote from: Autoquark on March 28, 2013, 08:27 ---2. I was also wondering about creating my own mod items. I guess you use ui.msg_choice to let the player choose an item slot to mod, but I can't find out from the wiki how to reference the player's equipped items. Is there any example code for this?

--- End quote ---

ui.msg_choice is actually what the real game uses, but there are more abstraction layers built up that you can use.  Mods are somewhat complicated, so here are the hooks from mod_power for you to base your stuff off of:

--- Code: --- OnUseCheck = function(self,being)
local item, result = being:pick_mod_item('P',being.techbonus)
if not result then return false end
if item ~= nil then self:add_property("chosen_item", item) end
return true
end,

OnUse = function(self,being)
if not self:has_property("chosen_item") then return true end
local item = self.chosen_item
if item.itype == ITEMTYPE_MELEE then
item.damage_sides = item.damage_sides + 1
elseif item.itype == ITEMTYPE_RANGED then
if item.damage_sides >= item.damage_dice then
item.damage_sides = item.damage_sides + 1
else
item.damage_dice = item.damage_dice + 1
end
elseif item.itype == ITEMTYPE_ARMOR then
item.armor = item.armor + 2
elseif item.itype == ITEMTYPE_BOOTS then
item.armor = item.armor * 2
end
item:add_mod('P')
return true
end,

--- End code ---
The whole dance with having to use OnUseCheck and the custom property is inelegant, but it allows the mod to not take any time when the player cancels it.  If you don't like that, here's the simpler version from before the change.

--- Code: --- OnUse = function(self,being)
local item, result = being:pick_mod_item('P',being.techbonus)
if not item then return result end
if item.itype == ITEMTYPE_MELEE then
item.damage_sides = item.damage_sides + 1
elseif item.itype == ITEMTYPE_RANGED then
if item.damage_sides >= item.damage_dice then
item.damage_sides = item.damage_sides + 1
else
item.damage_dice = item.damage_dice + 1
end
elseif item.itype == ITEMTYPE_ARMOR then
item.armor = item.armor + 2
elseif item.itype == ITEMTYPE_BOOTS then
item.armor = item.armor * 2
end
item:add_mod('P')
return true
end,

--- End code ---
Using :pick_mod_item will prompt the player, check for assemblies, and make sure you are allowed to mod the item with the given mod.


--- Quote ---3. Is there any easy way to prevent the level generator from generating the built-in items, or will I have to wait for total conversion mod support?

--- End quote ---

For a particular item, you can just do e.g.

--- Code: ---items.pistol.weight = 0

--- End code ---
If you want to get rid of all of them, you can just loop through before registering any of your own items

--- Code: ---for _, it in ipairs(items) do
  it.weight = 0
end

--- End code ---
Modifying prototypes after they are declared is a bit messy, but it's the only option for built-in things.


--- Quote ---Here's my item declaration:

--- End quote ---
Wow, what a useless error message.  It is failing because "gun" is not defined as a missile.  It has been renamed to "mgun".  (I think all the missiles gut "m" added at the beginning and all the shotgun-type missiles got "s" added to the beginning.)

Also, the id field should no longer be included in the table; the initial argument to register_item (e.g. "new_pulsecannon") will be used as the id.

SPTX:

--- Quote from: tehtmi on March 29, 2013, 02:22 ---It is failing because "gun" is not defined as a missile.  It has been renamed to "mgun".  (I think all the missiles gut "m" added at the beginning and all the shotgun-type missiles got "s" added to the beginning.)

Also, the id field should no longer be included in the table; the initial argument to register_item (e.g. "new_pulsecannon") will be used as the id.

--- End quote ---
I have the same error as this dude (and did the same mistake) however even after changing "gun" to "mgun" I still have the error.
Here is the incriminated code.

--- Code: ---register_item "SPTXsniperrifle"{
name = "Long range rifle",
    type = ITEMTYPE_RANGED,
sprite = SPRITE_CHAINGUN,
level = 2,
weight = 160,
psprite = SPRITE_PLAYER_SHOTGUN,
    ammo_id = "ammo",
    group = "weapon-shotgun",
    damage = "10d2",
damagetype = DAMAGE_BULLET,
    missile = "mgun",
    fire = 15,
    reload = 10,
    acc = 2,
    ammomax = 5,
flags = {IF_PUMPACTION,IF_SHOTGUN},
    desc = "A rifle designed to shoot targets at very long distances.",
    altfire = ALT_AIMED,
}
--- End code ---

Navigation

[0] Message Index

[#] Next page

Go to full version