Help wanted with programming and spriting new characters - the Belnades Sisters!

Luigifan18

Member
Hey, it's the Internet Wanderer, Luigifan! I've been watching people play SRB2 on YouTube and playing the game myself, and I want to try my hand at adding some of my own OCs to the game. Specifically, the Belnades sisters, who are some of the main characters of my ongoing fanfic/roleplay. (I have some other characters I'm trying to brainstorm and design, but it's the Belnades sisters who I'm currently focusing on.) I have attached a couple of .pdfs for my ideas on what the characters would be like when finalized (one being a little more detailed and organized than the other), and I also have the description posted on Reddit, but I'll put those links in a separate post so I don't have to wait for the mods to reapprove this one every time I update the files. (I did also try posting the descriptions here before I had any actual progress made, but it ran headlong into the character limits...) I have a very rough lump skeleton of Flora Belnades and a generic template version, and I've been taking bits of code from other add-ons, most prominently Almost Super Sonic (since I plan to use his energy meter as at least the visual basis for the energy meter system I'll be applying to the Belnades sisters; the functional basis will probably be something more like Modern Sonic), to try to get started, but ultimately, I'm not really sure how I'm supposed to achieve the goals I have in mind for these characters. Oh, and I've also been trying to build a map in Zone Builder to test out the characters' abilities. That is also a very rough framework right now. Anyways, I need help figuring out what I'm supposed to do to bring my characters to life in SRB2.

(And I don't even know yet what I'll do for the spriting...)

P.S. I ultimately want to put all four Belnades sisters in a single .pk3, like the StephChars or HorizonChars, but I feel like it would be best to build them in separate .pk3s so I can test them separately (and maybe release them separately) without any broken code getting in the way of what I'm currently working on. Oh, and I can't even get my template to appear on the character select screen when I try to load it...

EDIT: I've tried editing one of Tails's sprites to put him in a white dress (since that's Flora's preferred clothing) and give him a gold necklace chain with a white teardrop-shaped gemstone (since that's what Flora's Holy Necklace looks like). The result was... unsatisfactory. Come to think of it, maybe editing Tails's sprites to put clothing on him and modify his bangs isn't the best idea, since the Belnades sisters obviously don't share his exact build (for one thing, all four of them are women...)

2023-06-12 16_14_03-SLADE.png


EDIT: I've been studying the Lua functions, hooks, commands, etc. on the SRB2 wiki, and now I have some sort of idea of how to program the abilities to function how I want them. I still don't know the finer nuances of the code that would allow me to actually pull it off, but that's where you guys will come in. I'm preparing the scripting outlines right now. I'm not sure when they'll be ready.

EDIT: I've nixed the scripting outlines, I didn't even know enough Lua to get that done. I'm just tackling everything here and on the Discord as it comes up.

EDIT: I've made another thread in the Works In Progress board. I've outlined several of the issues I'm having in there.
 

Attachments

  • SRB2 Addon Ideas - The Belnades Sisters.pdf
    361.1 KB · Views: 58
  • SRB2 Addon Ideas - The Belnades Sisters (Advanced Commentary).pdf
    438 KB · Views: 55
  • Spriting Guidelines for the Belnades Sisters.pdf
    953.4 KB · Views: 44
Last edited:
I considered making a new thread for this issue, but I have this thread already, so... here we go.

Okay, I need some help with getting Cassandra's Copy Bolt working. It's supposed to set Cassandra's player.mo.copy variable to the skin or thing.type of the first player or enemy it hits, but I just get an error about tracer not being indexable when I try. Here's the error message...

Error:
WARNING: ...CL_Cassandra-Belnades.pk3|Lua/LUA_CASSANDRAABILITIES:131: attempt to index field 'tracer' (a nil value)
stack traceback:
    ...CL_Cassandra-Belnades.pk3|Lua/LUA_CASSANDRAABILITIES:131: in function <...CL_Cassandra-Belnades.pk3|Lua/LUA_CASSANDRAABILITIES:122>
    [C]: in function 'P_SpawnPlayerMissile'
    ...CL_Cassandra-Belnades.pk3|Lua/LUA_CASSANDRAABILITIES:110: in function <...CL_Cassandra-Belnades.pk3|Lua/LUA_CASSANDRAABILITIES:73>

Here's the relevant code...

Copy Bolt Hooks:
addHook("PlayerThink", function(player)
    if player.mo and player.mo.valid then
   
        if player.mo.skin ~= "cassandra_b" then
            return
        end
       
/*        if player.custom1down == nil then
            player.custom1down = 0
        end
       
        if player.cmd.buttons & BT_CUSTOM1 > 0 then
            player.custom1down = $1 + 1
        else
            player.custom1down = 0
        end*/
       
        if player.mo.copyboltcooldown == nil then
            player.mo.copyboltcooldown = 0
        end
       
        if player.mo.copyboltcooldown > 0 then
            if (leveltime%TICRATE) then
                player.mo.copyboltcooldown = $ - 1
            end
        end
       
        if player.mo.copy == nil then
            player.mo.copy = 0
        end
       
        if player.custom1down == 1
        and player.mo.copy == 0 //Can't use Copy Bolt if Cassandra already has a copied power
        and player.mo.mimicry == 0 //Can't use Copy Bolt if Cassandra is mimicking someone
        and player.mo.copyboltcooldown == 0 --Copy Bolt is NOT a machine gun
        and player.mo.energy >= 2*FRACUNIT then
            player.mo.energy = $ - 2*FRACUNIT
            local cbolt = P_SpawnPlayerMissile(player.mo, MT_CASSANDRA_COPYBOLT, nil)
            S_StartSoundAtVolume(player.mo, sfx_cblt, 60, nil)
            player.mo.copyboltcooldown = 1*TICRATE
        end
       
        if player.mo.copy ~= 0
        and player.tossflagdown == 1 then
            player.mo.copy = 0 --Discard copied power
        end
    end
end)

addHook("MobjMoveCollide", function(cbolt, thing) --tmthing == cbolt
    if thing.flags & MF_MONITOR then
        P_DamageMobj(thing, cbolt, cbolt.tracer, 1) --Copy Bolt breaks the monitor --cbolt.tracer == player according to P_SpawnPlayerMissile
        P_KillMobj(cbolt, thing, thing) --Copy Bolt stops moving
    end
   
    if thing.type == MT_PLAYER then
        if G_CoopGametype() == true
        or (G_GametypeHasTeams == true and thing.player.ctfteam == cbolt.tracer.ctfteam) then
            cbolt.tracer.copy = thing.player.mo.skin --copy the hit player's skin to use their abilities
            print(cbolt.tracer.copy) --Let's make sure Cassandra actually copied something
            P_KillMobj(cbolt, thing, thing) --stop Copy Bolt to avoid copying multiple skins in succession
            return --don't harm friendly players
        else
            cbolt.tracer.copy = thing.player.mo.skin --copy the hit player's skin to use their abilities (BEFORE doing damage and potentially killing them, which would make them null)
            print(cbolt.tracer.copy) --Let's make sure Cassandra actually copied something
            P_DamageMobj(thing, cbolt, cbolt.tracer, 1) --damage opposing players in competitive modes
            P_KillMobj(cbolt, thing, thing)
        end
    end
   
    if thing.flags & MF_ENEMY or thing.flags & MF_BOSS then
        cbolt.tracer.copy = thing.type --copy the ID of the hit enemy to obtain their ability (BEFORE doing damage and potentially killing them, which would make them null)
        print(cbolt.tracer.copy) --Let's make sure Cassandra actually copied something
        if thing.holyboltblock == nil then
            thing.holyboltblock = 3 --establish the sub-health meter used to govern Holy Bolt & Copy Bolt damage
            print("Target hit! "..thing.type.."'s current health: "..thing.health.." full HP, "..thing.holyboltblock.." sub-HP.") --check to make sure that Copy Bolt actually connected, particularly in the absence of pain state
        else
            thing.holyboltblock = $ - 3 --Copy Bolt always deals 1/2 damage
            print("Target hit! "..thing.type.."'s current health: "..thing.health.." full HP, "..thing.holyboltblock.." sub-HP.") --check to make sure that Copy Bolt actually connected, particularly in the absence of pain state
        end
        if thing.holyboltblock <= 0 then
            P_DamageMobj(thing, cbolt, cbolt.tracer, 1) --if a total of 6 sub-damage has been dealt, the target takes 1 real damage
            if thing.health >= 1 then
                thing.holyboltblock = $ + 6 --if the target isn't dead, add 6 sub-health (prior sub-damage can carry over)
                print("Target hit! "..thing.type.."'s current health: "..thing.health.." full HP, "..thing.holyboltblock.." sub-HP.") --check to make sure that Copy Bolt actually connected, particularly in the absence of pain state
            end
        end
        P_KillMobj(cbolt, thing, thing)
    end
end, MT_CASSANDRA_COPYBOLT)

The highlighted lines are the lines the error code refers to. (I had cbolt.tracer.mo.copy before, and that was causing an error, too, so I figured I could shorten tracer.mo to tracer since tracer would already be player.mo.) Isn't P_SpawnPlayerMissile supposed to set the player as the tracer by default?

(Come to think of it, I may be getting target and tracer mixed up, given the weird way projectiles work in SRB2. I'll try fixing it that way.)



EDIT: Replacing tracer with target worked! I had to add another line of code specifying that Copy Bolt couldn't copy its target to prevent it from immediately copying Cassandra herself (Department of Redundancy Department much?), but once I did, Cassandra was able to copy the abilities of Badniks as intended! (I did find that copying a skin returned an "attempt to compare number to string" error, but I'll worry about that when I'm actually ready to set up player copying and mimicry.)
 

Attachments

  • CL_Cassandra-Belnades.pk3
    2.1 MB · Views: 55
  • log-2023-07-28_10-18-12.txt
    7.7 KB · Views: 49
Last edited:
…Hey, does anyone have any ideas why Flora's Blue Splash isn't working? I can't manage to get the icicles to spawn, neither in 2D nor in 3D.
 

Attachments

  • CL_Flora-Belnades.pk3
    1.8 MB · Views: 53
Last edited:
So, I tried to make an iterative function to enable Flora's Holy Flame to bust walls, and it's generating an error. Here's my code and the error.

Holy Flame Wall Smashing:
--Breaking bustable walls and spikes
addHook("MobjLineCollide", function(mobj, line)
    local backfront = {line.frontsector, line.backsector}
  
for rover in backfront.ffloors{
    if (mobj.z <= ffloor.topheight or mobj.z >= ffloor.bottomheight) then
        if ffloor.master.special == 252
        or ffloor.master.special == 253
        or ffloor.master.special == 254
        or ffloor.master.special == 255
        or ffloor.master.special == 256 then
            EV_CrumbleChain(backfront, rover) --Holy Flame can break bustable walls
            return true
        else
            continue
        end
    end}
end, MT_HOLYFLAMECORE)

addHook("MobjLineCollide", function(mobj, line)
    local backfront = {line.frontsector, line.backsector}
  
for rover in backfront.ffloors{
    if (mobj.z <= ffloor.topheight or mobj.z >= ffloor.bottomheight) then
        if ffloor.master.special == 252
        or ffloor.master.special == 253
        or ffloor.master.special == 254
        or ffloor.master.special == 255
        or ffloor.master.special == 256 then
            EV_CrumbleChain(backfront, rover) --Holy Flame can break bustable walls
            return true
        else
            continue
        end
    end}
end, MT_HOLYFLAME)

The first highlighted line is line 216 in my full Lua script, which is what's causing the error report:

It'd be nice if you told me WHAT symbol was unexpected...:
WARNING: ...\SLADE\The Belnades Sisters\CL_Flora-Belnades.pk3|Lua/LUA_FLORAABILITIES:216: unexpected symbol near 'if'



UPDATE: I reconfigured the iterative function to add some missing keywords, and it's not returning an error on load now, but it is returning an error when Holy Flame is used during gameplay. Here's the new code:

Holy Flame Wall Smashing:
--Breaking bustable walls and spikes
addHook("MobjLineCollide", function(mobj, line)
    local backfront = {line.frontsector, line.backsector}
  
    for rover in backfront.ffloors.iterate() do
        if (mobj.z <= ffloor.topheight or mobj.z >= ffloor.bottomheight) then
            if ffloor.master.line.special == 252
            or ffloor.master.line.special == 253
            or ffloor.master.line.special == 254
            or ffloor.master.line.special == 255
            or ffloor.master.line.special == 256 then
                EV_CrumbleChain(backfront, rover) --Holy Flame can break bustable walls
                return true
            else
                return
            end
        else
            continue
        end
    end
end, MT_HOLYFLAMECORE)

addHook("MobjLineCollide", function(mobj, line)
    local backfront = {line.frontsector, line.backsector}
  
    for rover in backfront.ffloors.iterate() do
        if (mobj.z <= ffloor.topheight or mobj.z >= ffloor.bottomheight) then
            if ffloor.master.line.special == 252
            or ffloor.master.line.special == 253
            or ffloor.master.line.special == 254
            or ffloor.master.line.special == 255
            or ffloor.master.line.special == 256 then
                EV_CrumbleChain(backfront, rover) --Holy Flame can break bustable walls
                return true
            else
                return
            end
        else
            continue
        end
    end
end, MT_HOLYFLAME)

The highlighted lines are where the new error is generated (with the first highlighted line being line 215 and the second highlighted line being line 236):

What's an ffloor?:
WARNING: ...Sisters\CL_Flora-Belnades.pk3|Lua/LUA_FLORAABILITIES:215: attempt to index field 'ffloors' (a nil value)
stack traceback:
    ...Sisters\CL_Flora-Belnades.pk3|Lua/LUA_FLORAABILITIES:215: in function <...Sisters\CL_Flora-Belnades.pk3|Lua/LUA_FLORAABILITIES:212>

WARNING: ...Sisters\CL_Flora-Belnades.pk3|Lua/LUA_FLORAABILITIES:236: attempt to index field 'ffloors' (a nil value)
stack traceback:
    ...Sisters\CL_Flora-Belnades.pk3|Lua/LUA_FLORAABILITIES:236: in function <...Sisters\CL_Flora-Belnades.pk3|Lua/LUA_FLORAABILITIES:233>
 

Attachments

  • LUA_FLORAABILITIES.txt
    61.9 KB · Views: 44
  • CL_Flora-Belnades.pk3
    1.8 MB · Views: 48
Last edited:
I would definitely appreciate advice on rewriting the Belnades sisters's SOC files to avoid running off the character select screen. Especially for Cassandra, whose text is so long that it actually generates a warning upon loading the add-on.
 

Who is viewing this thread (Total: 1, Members: 0, Guests: 1)

Back
Top