Skip to content
A-MC Creative Development

A-MC Creative Development

Programming, Music, Tech, Hardware, Amiga, Commodore, Retrogaming and probably much more :)

  • Home
  • SOFTWARE
    • Hollywood Source & Libraries
    • APPBuilder Tool
    • HFinder 2017
    • HGUI
    • GEMZ
    • White Dot
  • Allanon’s Music Corner
  • About Me
  • MANUALS
  • Hire Me!
  • Privacy Policy
  • Toggle search form

Generic RPG Engine : Dev Log #1

Posted on March 26, 2025March 26, 2025 By allanon No Comments on Generic RPG Engine : Dev Log #1

INTRODUCTION

I’ve always been a lover of RPGs and JRPGs and one of my dreams has always been to create my own game with its very own RPG Engine.

To be honest, I’ve tried several times to create a game of this kind, but I always ended up overcomplicating things, documenting the code too little, and after a few breaks that life forces you to take, I always parked the project to oblivion.

A few days ago, while I was digging into my hard drive to check all the projects that were started and never finished, I stumbled upon a project from a few years ago, yet another attempt that was then suspended.

I started checking what I did, and I must admit that this time I had done a good job, even if not free from defects.

My main ambition is to create an engine that is as flexible as possible, so that it can be adapted to the most varied needs. A project like this is extremely complicated because an RPG has an infinite amount of data to organize and manage that is pretty scary: just think about all the attributes of the creatures, the weapons, the shields, the equipment, the consumables, the spells, the skills, in short: a lot of data to handle that is interconnected with each other.

What I had done however had some parts that were not flexible because ‘hardcoded’, that parts couldn’t be customizable, so I decided to take up the project again and make the engine (still incomplete) as customizable as possible.

I also decided to document what I’m doing in the hope of helping anyone who wants to try to get their hand dirty with a similar project. I’m not claiming that my implementation is the right way, but perhaps it can be used to give some ideas to whoever want to try to build something like this from scratch, and that’s the main reason for this devlog series!

Despite all my efforts some little things are hardcoded just because it is impossible to abstract anything!

This first post is going to be a bit long, be prepared 🙂

WHAT I’M USING TO CODE

I use Hollywood-MAL as programming language, it’s very similar to Lua but it includes an infinite number of commands that satisfy the most diverse needs. If you are familiar with Lua you will understand the code without problems, at least in these first steps where no multimedia content is involved at all.

Why such an obscure language like Hollywood-MAL?

Hollywood is a well know language on Amiga-land but it’s not just for Amiga and Amiga-like systems, it compiles for almost all the platforms and architectures around, have a look at its home page if you are curious.

Said that, I have been using Hollywood for many years with great satisfaction and since it is really similar to lua which I love, I don’t really see why I shouldn’t use it for a project like this!

I will use object-oriented programming as much as possible, that is: data structures (objects) with methods and other features that (at least from my point of view) simplify reading the source. Readibility and documentation is really important in an huge project like this and writing this articles will also let me document it and clearify points that I could forget.

Furthermore I will try to keep the various topics separated with separated sources (modules) that will then be included in the main project. At one point I’ll publish the source code because I trust in open source and in sharing each other knowledge.

My main editor of choice is TextAdept, one of the best text editor I ever used: it’s very light and highly customizable, infact I’ve customized it for my own needs with syntax highlighting for Hollywod and for some of my own library I often use. My development system is Linux Manjaro. I switched to Manjaro some years ago, and I’m so happy I’ve found the courage to switch to Linux (from Windows).

This first, quite long post, explains what I’ve implemented so far, things can change during the development since this is a work in progress!

DAMAGE TYPES

The first aspect I’m going to analyze are the damage types. What I want to implement is completely abstracted so that everyone can define and use its very own damage types, but why this feature is important?

Well, it’s important for at least these reasons:

  • Weapons and Magic can inflict a specific type of damage.
  • Creatures and races can be more sensible to certain type of damage, and can resist to some of them.
  • Equipment can protect a creature with different efficiency depending on the received damage type.
  • …more

For example a sword could inflict physic damage, more specifically cut damage, a spear could also inflict physic damage but more specifically pierce damage, and the same could also be applied to magic.

So I decided to implement damage types as group and sub-groups, for example physic and magic are two groups while cut, pierce, impact are sub-groups of physic damage and fire, water, light and dark are sub-groups of magic damage.

But what I said above are just examples, I want to be totally free to define such groups and sub-groups as I wish so I implemented the creation of damage types with this method:

app.damage_type:add(args)

The args parameter represent a table that accepts two fields named group and sub that are used to define the damage type.

Here is an example:

app.damage_type:add({ group = "physic", sub = "pierce")
app.damage_type:add({ group = "physic", sub = "cut")
app.damage_type:add({ group = "physic", sub = "impact")

The created damage types can then be referenced later using a string with the notation group.sub or just group, this last form will includes all the sub-groups when referenced.

This way I avoid creating hardcoded structures and fixed damage types: I’m able to create something never seen before like:

app.damage_type:add({ group = "sound", sub = "resonance" })
app.damage_type:add({ group = "sound", sub = "subwaves" })
app.damage_type:add({ group = "psychic", sub = "mind" })

To complete the damage types argument, all of these definitions are stored into a table like this:

app.damage_types =
  { sound =
    { resonance = true,
      subwaves = true },
    psychic =
    { mind = true }
    }

It’s easy to find all the sub-groups of a given group. The true value you see to the right of the sub-group means that it’s active and can be used. It may be switched off for testing reasons or other development needs.

There is also a :get() method that returns different data depending on what you are asking for:

result = app.damage_type:get(args)

args is a table that accepts the group and sub fields, like the :add() method, but this time sub is optional and you can get all the sub-groups if you just ask for the main group.

From my internal documentation:

result = app.damage_type:get(args)
Retrieve the specified damage type.
If asked for a group it returns the table, if asked for sub returns if it's enabled or not, if what asked does not exists prints a warning and returns False.

INPUT
  args     [TBL] A table holding these items:
    .group  [STR] Group name (Physic, Magic, ...)
    .sub    [STR][OPT] Sub group (Pierce, Cut, Fire, Dark, ...)
  -- or --
  args     [STR] A string using the format 'group' or 'group.sub'

OUTPUT
  result    [TBL]|[BLN] See the description above. 

The fact that this method returns False if the damage type doesn’t exists is important because i can use :get() also to validate other fields (in other functions/methods) that require a damage type as data type.

Let’s conclude this part with my test code:

; DAMAGE TYPES DEFINITION
; =======================
DBG.Console.Out("Creating damage types...", DBG.Hilight, app.dch.main)
app.damage_type:add({ group = "physic", sub = "impact"  })
app.damage_type:add({ group = "physic", sub = "cut"     })
app.damage_type:add({ group = "physic", sub = "pierce"  })
app.damage_type:add({ group = "physic", sub = "health"  })
app.damage_type:add({ group = "magic",  sub = "fire"    })
app.damage_type:add({ group = "magic",  sub = "air"     })
app.damage_type:add({ group = "magic",  sub = "water"   })
app.damage_type:add({ group = "magic",  sub = "dark"    })
app.damage_type:add({ group = "magic",  sub = "necro"   })
app.damage_type:add({ group = "magic",  sub = "blood"   })
app.damage_type:add({ group = "magic",  sub = "nature"  })
app.damage_type:add({ group = "magic",  sub = "restore" })

and here is the console output I get:

My RPG Engine while defining new damage types.
The image has the following text:
000000| Creating damage types...
000000| app.damage_type:add() --- creating new group 'physic' ---
000001| app.damage_type:add() physic.impact
000002| app.damage_type:add() physic.cut
000003| app.damage_type:add() physic.pierce
000003| app.damage_type:add() physic.health
000004| app.damage_type:add() --- creating new group 'magic' ---
000004| app.damage_type:add() magic.fire
000005| app.damage_type:add() magic.air
000005| app.damage_type:add() magic.water
000006| app.damage_type:add() magic.dark
000006| app.damage_type:add() magic.necro
000007| app.damage_type:add() magic.blood
000007| app.damage_type:add() magic.nature
000008| app.damage_type:add() magic.restore

CREATURE’S ATTRIBUTES

Creature’s attributes are parameters that determine how much is strong or weak a certain creature in specific tasks that are based on such values.

A typical example is the strenght attribute: generally a higher value make the physic attacks stronger causing more damage.

But as I stated earlier I don’t want to hardcode these attributes for two main reasons:

  1. Every game is different: you may want to use different or unconventional stats (unconventional attribute names), a name like psychic_power for example in not common in RPG games.
  2. We could hardcode a full set of common stats but you may use only a few of them wasting resources.

Another important feature I added are computed stats: stats that has a value calculated at runtime, attributes that use a formula based on other attributes. For example we could have an attribute like this:

smartness = intelligence*0.5+intuition*0.3

where intelligence and intuition are two existing attributes.

Let’s see how I managed to implement completely programmable attributes, here is the main data structure:

app.char_attr =       ; attribute's structure
{ name     = "",
  type     = 0,
  computed = False,
  formula  = "",
  vital    = False,
  inverse  = False }

Let’s see what these fields mean:

  • name : [STR] Attribute’s name (intelligence, mana, life, etc…)
  • type : [CNS] Attribute’s data type (#VTYPE_STR for strings, but here it’s not used, #VTYPE_PERC for percentuals, #VTYPE_NUM for numbers)
  • computed : [BLN] True if it’s a computed attribute (it has a formula)
  • formula : [STR] Holds the formula for computed attributes
  • vital : [BLN] Means that when this attribute reaches 0 the character dies.
  • inverse : [BLN] Means that we have to manage the values in inverse mode: 0 is the maximum value, maximum value is handled as the minimum

NOTE: [BLN] stands for boolean, [STR] for string, [CNS] for constant.

The last two fields are interesting because they allow to define something unusual like, for example, an attribute fatigue, it could let the creature die when it reaches its maximum value. The tipical life attribute instead let the creature die when it reaches zero.

Some additional words are needed for the formula field: it holds a string used to compute the real values based on other attributes.

Premise: attributes have 3 fixed sub-attributes (hardcoded, sorry!) that are: current (current stat value), maximum (stat cap, its maximum value) and regen (regeneration value at each turn, think of stamina that regenerates over time, or mana for example).

And that’s the reason why within formulas we have to use only the attribute’s name: because to compute the current value the attribute.current will be used, to compute the maximum value the attribute.maximim value will be accessed, and so on.

In our previously example:

smartness = intelligence*0.5+intuition*0.3

will use intelligence.current and intuition.current to compute the smartness.current value.

Sub-attributes (current, maximum and regen) can be enabled or disabled at will, they are stored is a table called app.subAttrs like this:

app.subAttrs =
{ current = True,
  maximum = True,
  regen = True }

To create an attribute I coded this method:

app.char_attr:add(args)
  ; Adds a new attribute to the character's template
  ; 
  ; INPUT
  ;   args
  ;     .name:      [STR] Attribute name
  ;     .type:      [CNS] Attribute type (#VTYPE_...)
  ;     .computed:  [BLN] True if it's a computed attribute
  ;     .formula:   [STR] Formula for computed attributes
  ;     .vital:     [BLN] True: when the attribute reaches 0 the char dies
  ;     .inverse:   [BLN] True: we have to manage the value in inverse mode: 0
  ;                 is the max, max is the min.

To check if an attribute exists I coded this other method:

result = app.char_attr:exists(attr)
  ; Checks the specified creature's attribute and returns True if it exists
  ; otherwise returns False. 'attr' can also be passed in the 'attr.sub'.
  ; 'sub' can only have one of the following values: 'current', 'maximum'
  ;  or 'regen'.
  ; False is also returned if the sub-attribute is disabled.
  ;
  ; INPUT
  ;   attr : [STR] The attribute name we want to check
  ;
  ; OUTPUT
  ;   result : [BLN] True if the attribute exists otherwise False.

Finally here is my test code:

; CREATURE'S ATTRIBUTES
; =====================
DBG.Console.Out("Creating creature's attributes...", DBG.Hilight, app.dch.main)
app.char_attr:add({ name = "life",         type = #VTYPE_NUM, computed = False, formula = "", vital = True, inverse = False })
app.char_attr:add({ name = "constitution", type = #VTYPE_NUM, computed = False, formula = "", vital = True, inverse = False })
app.char_attr:add({ name = "stamina",      type = #VTYPE_NUM, computed = False, formula = "", vital = False, inverse = False })
app.char_attr:add({ name = "dexterity",    type = #VTYPE_NUM, computed = False, formula = "", vital = False, inverse = False })
app.char_attr:add({ name = "willpower",    type = #VTYPE_NUM, computed = False, formula = "", vital = False, inverse = False })
app.char_attr:add({ name = "intelligence", type = #VTYPE_NUM, computed = False, formula = "", vital = False, inverse = False })
app.char_attr:add({ name = "mana",         type = #VTYPE_NUM, computed = False, formula = "", vital = False, inverse = False })
app.char_attr:add({ name = "fatigue",      type = #VTYPE_NUM, computed = False, formula = "", vital = True, inverse = True })
app.char_attr:add({ name = "strength",     type = #VTYPE_NUM, computed = False, formula = "", vital = False, inverse = False })
app.char_attr:add({ name = "magic_power",  type = #VTYPE_NUM, computed = True,  formula = "life*0.25+willpower*0.25", vital = False, inverse = False })
app.char_attr:add({ name = "physic_power", type = #VTYPE_NUM, computed = True,  formula = "life*0.25+strength*0.25",  vital = False, inverse = False })

That produce the following output:

My RPG Engine while defining new attributes.
The image shows this text:
000009| Creating creature's attributes...
000009| app.char_attr:add() life (type: Number, computed: No, formula: , vital: Yes, inverse: No)
000010| app.char_attr:add() constitution (type: Number, computed: No, formula: , vital: Yes, inverse: No)
000011| app.char_attr:add() stamina (type: Number, computed: No, formula: , vital: No, inverse: No)
000012| app.char_attr:add() dexterity (type: Number, computed: No, formula: , vital: No, inverse: No)
000013| app.char_attr:add() willpower (type: Number, computed: No, formula: , vital: No, inverse: No)
000013| app.char_attr:add() intelligence (type: Number, computed: No, formula: , vital: No, inverse: No)
000014| app.char_attr:add() mana (type: Number, computed: No, formula: , vital: No, inverse: No)
000015| app.char_attr:add() fatigue (type: Number, computed: No, formula: , vital: Yes, inverse: Yes)
000016| app.char_attr:add() strength (type: Number, computed: No, formula: , vital: No, inverse: No)
000016| app.char_attr:add() magic_power (type: Number, computed: Yes, formula: life*0.25+willpower*0.25, vital: No, inverse: No)
000017| app.char_attr:add() physic_power (type: Number, computed: Yes, formula: life*0.25+strength*0.25, vital: No, inverse: No)

STATUSES

If you have played an RPG or a JRPG you have noticed that, especially during battles, a creature can be afflicted by the so called status change like freeze, sleep, haste, slow, etc… This is a must have for every wannabe RPG Engine project!

A status change is something that alters the usual creature’s behaviour, forbidding certain actions or altering his normal actions flow.

The first step I did to allow the implementation of status changes was to define a list of global variables that a status can alter:

; List of variables accessible by the status definition
app.status_vars =
{ turn_position     = True,
  act_randomly      = True,
  target_allies     = True,
  target_foes       = True,
  can_cast          = True,
  cannot_cast       = True,
  can_summon        = True,
  can_use_item      = True,
  can_equip         = True,
  can_defende       = True,
  can_learn         = True,
  get_damage        = True,
  do_damage         = True,
  change_status     = True,
  is_locked         = True,
  can_use_abilities = True,
  can_be_targeted   = True,
  immunity          = True,
  clear_permanent   = True,
  clear_status      = True }

And here is a description for each of them, but please note that you may encounter some variable’s names that are explained later, like alterValue which means alteration value.

  • turn_position
    This variable is calculated before the battle turn is started and determines when the creature will take action positioning it into an action queue. A status change can target this variable to modify the creature’s position in the said queue.
    Tipical examples are slow and haste statuses that can move the creature position above or below the other creatures positions in the action queue.
  • act_randomly
    This is a simple flag that is used to determine if the creature should be controlled by the player/AI or act randomly. Normally it’s set to False. A tipical example is the confusion status.
  • target_allies
    This flag is used to determine if the creature can target his allies. Normally it’s set to True.
  • target_foes
    This flag is used to determine if the creature can target his foes. Normally it’s set to True.
  • can_cast
    Determines if the creature can cast spells.
  • cannot_cast
    Same as above but inverted, determines if the creature cannot cast spells.
    This flag and the above one are used to determine if the creature can cast spells and, if specified in subTarget, for which damage type. Since the damage type is involved it can also be used to forbid some physical attack too.
    An example could be the classic silence that could be easily implemented using:
    can_cast with subTarget="magic" and alterValue=False which means: Not(can_cast[magic])
    OR
    cannot_cast with subTarget="magic" and alterValue=True.
  • can_summon
    Determines if a summon scroll can be read and executed and, if specified, for which damage type (in this case it is intended as magic type) using subTarget.
  • can_use_item
    Determines if the creature can use items.
  • can_equip
    Determines if the creature can change equipment.
  • can_defende
    Determines if the creature can select defend as battle action.
  • can_learn
    Determines if the creature can learn new magics or new abilities.
  • get_damage
    Determines if there is a variation of damage received and, if specified with subTarget, for which damage type. This affect also curative effects, which are just negative damages.
  • do_damage
    Determines if there is a variation of inflicted damage and, if specified with subTarget, for which damage type. Same as above: it affect also curative effects, which are just negative damages.
  • change_status
    Determines if the creature can be affected by status changes.
  • is_locked
    Determines if the creature is completely locked resulting in a complete turn skip.
  • can_use_abilities
    Determines if the creature can use learned abilities and, if specified with subTarget, for which damage type.
  • can_be_targeted
    Determines if the creature can be targeted by other creatures. For example invisibility could be inplemented using this status.
  • immunity
    Determines if the creature is immune to all or one damage type (using subTarget).
  • clear_permanent
    Used to clear one or more permanent status, alterValue indicates how many permanent status to remove (randomly). 0 clears all permanent statuses.
  • clear_status
    Used to clear one or more non-permanent status, alterValue indicates how many non-permanent status to remove (randomly). o clears all non-permanent statuses.

They is a lot of stuff but i think that should cover almost any case.

Now that we had this long introduction let’s see how a status change is defined using the following data structure:

  app.char_status =
    { name = "",
      list = { }
      }

Where list holds one or more entry like this:

{ target = "",        ; internal target's name
  subTarget = "",     ; sub target, where needed
  alterMode = 0,      ; alteration mode (#ALTMODE_ABS, _ADD, _PERC, _BOOL)
  alterValue = 0,     ; alteration value
  permament = False,  ; permanent change?
  duration = 0 }      ; place holder for when the status will be applied

That’s it: a status change can inflict one or more changes and each change is determined by the list entry. The char_status.name field is used to store an string identifier. Let’s see the list entry fields one by one:

  • target
    It’s the internal target’s name, the internal variable’s name listed earlier.
  • subTarget
    Some targets need this field to determine the affected damage type. If not specified it means ‘all damage types’.
  • alterMode
    Alteration mode determines how the alterValue is interpreted and can be set with one of the following constants: #ALTMODE_ABS, #ALTMODE_ADD, #ALTMODE_PERC, #ALTMODE_NONE
  • alterValue
    This field is used to set the amount of variation or as boolean values to be used as switches.
  • permanent
    If this field is set to True the status will never expire
  • duration
    This field is just a placeholder, when we will use status changes to define the alterations (please don’t cry, I know it’s complex!) it will be filled automatically with the alteration’s duration.

Now let’s see a couple of examples before closing this topic. Let’s see 3 real examples:

FREEZE STATUS

app.char_status:add(
  { name = "freeze", 
    list = { 
      { target = "is_locked",
        alterMode = #ALTMODE_BOOL,
        alterValue = True } } })

It seems pretty simple isn’t it? I’m creating a freeze status that sets the global variable is_locked to True.

MADNESS STATUS

app.char_status:add(
  { name = "madness", 
    list = { 
     { target = "act_randomly", 
       alterMode = #ALTMODE_BOOL, 
       alterValue = True } } })

This is pretty similar to the previous one: I’m creating a madness status by setting the global variable act_randomly to True.

CURSE OF WEAKNING

app.char_status:add(
  { name = "curse_of_weakening", 
    list = { 
      { target = "get_damage", 
        alterMode = #ALTMODE_PERC, 
        alterValue = 1.50 },
      { target = "do_damage", 
        alterMode = #ALTMODE_PERC, 
        alterValue = 0.50 } } })

This last example is a bit more complex, it uses two entries to define a weakening status called curse of weakening. It apply two effects, the first one increase each damage taken (get_damage) by 50%, while the second one decrease any damage done (do_damage) by 50%. With damage I also intend curative variations which are just negative damages.
It is also possible to apply the damage variation to only a damage type like magic or physic.pierce (using of course the previously examples since damage types are fully customizable).

Finally let’s have a look at my test code:

; CREATURE'S STATUSES
; ===================
DBG.Console.Out("Creating statuses...", DBG.Hilight, app.dch.main)
app.char_status:add({ name = "freeze", list = 
  { { target = "is_locked", alterMode = #ALTMODE_BOOL, alterValue = True } } })
app.char_status:add({ name = "madness", list = 
  { { target = "act_randomly", alterMode = #ALTMODE_BOOL, alterValue = True } } })
app.char_status:add({ name = "curse_of_weakening", list = 
  { { target = "get_damage", alterMode = #ALTMODE_PERC, alterValue = 1.50 },
    { target = "do_damage", alterMode = #ALTMODE_PERC, alterValue = 0.50 } } })
app.char_status:add({ name = "bless_of_golems", list = 
  { { target = "get_damage", subTarget = "physic", alterMode = #ALTMODE_PERC, alterValue = 0.50 },
    { target = "get_damage", subTarget = "magic", alterMode = #ALTMODE_PERC, alterValue = 1.60 },
    { target = "immunity", subTarget = "magic.restore", alterMode = #ALTMODE_BOOL,  alterValue = False } } })
app.char_status:add({ name = "shadow_form", list = 
  { { target = "can_cast", subTarget = "physic", alterMode = #ALTMODE_BOOL, alterValue = False },
    { target = "can_be_targeted", subTarget = "", alterMode = #ALTMODE_BOOL, alterValue = False },
    { target = "do_damage", subTarget = "magic", alterMode = #ALTMODE_PERC, alterValue = 1.90 } } })
app.char_status:add({ name = "silence", list = 
  { { target = "can_cast", subTarget = "magic", alterMode = #ALTMODE_BOOL, alterValue = False } } })
app.char_status:add({ name = "haste", list = 
  { { target = "turn_position", alterMode = #ALTMODE_PERC, alterValue = 0.25 } } })
app.char_status:add({ name = "slow", list = 
  { { target = "turn_position", alterMode = #ALTMODE_PERC, alterValue = 1.75 } } })
app.char_status:add({ name = "stoned_hands", list = 
  { { target = "can_cast", subTarget = "physic", alterMode = #ALTMODE_BOOL, alterValue = False } } })
app.char_status:add({ name = "forbid_fire_magic", list = 
  { { target = "cannot_cast", subTarget = "magic.fire", alterMode = #ALTMODE_BOOL, alterValue = True } } })
app.char_status:add({ name = "bless_of_the_fire_bird", list = 
  { { target = "do_damage", subTarget = "magic.fire", alterMode = #ALTMODE_PERC, alterValue = 2.50 } } }) 
app.char_status:add({ name = "curse_of_mist", list = 
  { { target = "do_damage", subTarget = "", alterMode = #ALTMODE_PERC, alterValue = 0.70, permanent = True },
    { target = "get_damage", subTarget = "", alterMode = #ALTMODE_PERC, alterValue = 1.30, permanent = True } } })
app.char_status:add({ name = "magic_weakness", list = 
  { { target = "do_damage", subTarget = "magic", alterMode = #ALTMODE_PERC, alterValue = 0.50 } } })

And here is the console output I get:

The screenshot shows the output I get from my RPG Engine when I define the test status changes:
000017| Creating statuses...
000017| app.char_status:add() freeze
000018|  0. target: is_locked subTarget: , alterValue: Yes (BOOL), permanent: No
000019| app.char_status:add() madness
000019|  0. target: act_randomly subTarget: , alterValue: Yes (BOOL), permanent: No
000020| app.char_status:add() curse_of_weakening
000020|  0. target: get_damage subTarget: , alterValue: 1.5 (PERC), permanent: No
000021|  1. target: do_damage subTarget: , alterValue: 0.5 (PERC), permanent: No
000023| app.char_status:add() bless_of_golems
000023|  0. target: get_damage subTarget: physic, alterValue: 0.5 (PERC), permanent: No
000024|  1. target: get_damage subTarget: magic, alterValue: 1.6 (PERC), permanent: No
000025|  2. target: immunity subTarget: magic.restore, alterValue: No (BOOL), permanent: No
000026| app.char_status:add() shadow_form
000027|  0. target: can_cast subTarget: physic, alterValue: No (BOOL), permanent: No
000027|  1. target: can_be_targeted subTarget: , alterValue: No (BOOL), permanent: No
000028|  2. target: do_damage subTarget: magic, alterValue: 1.9 (PERC), permanent: No
000029| app.char_status:add() silence
000029|  0. target: can_cast subTarget: magic, alterValue: No (BOOL), permanent: No
000030| app.char_status:add() haste
000030|  0. target: turn_position subTarget: , alterValue: 0.25 (PERC), permanent: No
000031| app.char_status:add() slow
000031|  0. target: turn_position subTarget: , alterValue: 1.75 (PERC), permanent: No
000032| app.char_status:add() stoned_hands
000032|  0. target: can_cast subTarget: physic, alterValue: No (BOOL), permanent: No
000033| app.char_status:add() forbid_fire_magic
000034|  0. target: cannot_cast subTarget: magic.fire, alterValue: Yes (BOOL), permanent: No
000034| app.char_status:add() bless_of_the_fire_bird
000035|  0. target: do_damage subTarget: magic.fire, alterValue: 2.5 (PERC), permanent: No
000036| app.char_status:add() curse_of_mist
000036|  0. target: do_damage subTarget: , alterValue: 0.7 (PERC), permanent: Yes
000037|  1. target: get_damage subTarget: , alterValue: 1.3 (PERC), permanent: Yes
000037| app.char_status:add() magic_weakness
000038|  0. target: do_damage subTarget: magic, alterValue: 0.5 (PERC), permanent: No

In next post I’ll discuss how I implemented Alterations and how I’m implementing items as a root data structure and the its first derivate: weapons.

I hope I haven’t bored you with this very long lalk!

Hollywood, Programming Tags:Attributes, Coding, Damage Type, HollywoodMAL, JRPG, Lua, programming, RPG, RPG Engine, Status Changes

Post navigation

Previous Post: 2025 March progress report + Extras
Next Post: Wow! April is almost over already!

Related Posts

LSliders, sliders LSliders : Horizontal & Verical sliders using Layers Hollywood
ANSI Lib 1.4 release Hollywood
g2d G2D Library for Hollywood MAL released. Hollywood
Helpers Library v1.6 part 2 Hollywood
Tables Library updated and ready for you! Hollywood
July update! Hollywood

Leave a ReplyCancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Support me on Patreon!

My Patreon PageSupport me on Patreon!

Support with PayPal

Support me with a small donation!

Recent Posts

  • 2026 Update : run baby, run!
  • The last progress report of the year!
  • November’s round up!
  • Progress Report: September

Categories

Archives

Recent Comments

  • allanon on AmiCloud Beta 04 released! The DropBox alternative
  • Paul Issegalö on AmiCloud Beta 04 released! The DropBox alternative
  • allanon on AppBuilder v2.0 released

My Music Page on Facebook

My Music Page on Facebook

My Twitter

My Tweets

I’m on Spotify and Soundcloud!

My Spotify PageListen to my music!
My Soundcloud PageListen to my music!
Privacy & Cookies : This site use cookies. Please take a moment to review our privacy policy. Our Cookie and Privacy Policy

Follow me on Mastodon

Mastodon.Uno

Copyright © 2026 A-MC Creative Development.

Powered by PressBook Masonry Dark

 

Loading Comments...