• Do not use Works in Progress as a way of avoiding the releases system! Works in Progress can be used for sharing early betas and for getting suggestions for improvement. Releases of finished content are not allowed in this forum! If you would like to submit a finished addon, click here for instructions on how to do so.

The Belnades Sisters — WIP (Spriting & Coding Assistance Needed)

Luigifan18

Member
So, for the past few months, I've been diligently working on bringing my main Sonic OCs — Annie, Sonja, Flora, and Cassandra Belnades — to Sonic Robo Blast 2. Progress hasn't always been smooth, but all 4 are currently in a semi-playable state. However, I still have a long way left to go, and I think I'm nearing the limits of what I can accomplish on my own with just the wiki as a guide, so I'm going to need some community assistance in fixing the bugs and implementing the missing features!



Concept tweaks after the start of programming:

  • The Phazon in Metroid Vanguard is not an instant-kill sector, and minecarts don't use DMG_INSTAKILL either; they both use P_KillMobj. I've been working with Golden Shine to develop a specialized Phazon resistance passive for Annie, but I'm not sure what to do with minecarts yet.
  • Sonja's Chrono Evasion now includes a flash jump (read: a vertical flash step) and a counterattack.
  • Flora's Holy Lightning now has two Easter Egg variations that are intentionally mis-coded to either stay in place upon deployment or follow Flora around to zap any enemy that gets too close for comfort.



Things that still need to be added:

  • Each of the Belnades sisters need their own sprites and animations (Tails's sprites are currently being used as a placeholder).
  • The Belnades sisters' non-standard actions have not had their corresponding states implemented yet. (I'm not sure if all of them actually need states...)
  • Sound effects and visual effects for various actions (including Vixen Vortex, Sonja's time slow and rewind, Flora's spells, and Cassandra's copy actions) have not been added yet.
  • The console command to allow the player to freely adjust their current energy in devmode is not implemented yet.
  • I'd like to enable Annie's healing to mitigate the effects of and/or speed up recovery from some of the status effects in the MonitorsPlus mod, such as poison, as well as some status effects in the base game, like Canarivore gas-induced slowdown.
  • Annie's Emergency Carry is not implemented yet. I thought I could use Dirfex's carrying code as a placeholder, but in hindsight, that probably won't work.
  • The code for Annie's tweaks to other players' respawn behavior (and the console commands to regulate said tweaks) is incomplete, and I'm not sure how to proceed.
  • Sonja's time slow and rewind do not currently have any effect on mobjs, FOFs, polyobjects, pushers, scrollers, or, well, anything except for the level timer. (Due to technical limitations, Sonja also only affects her own level timer at the current time.)
    • I recently added code to make the time slow work on mobjs, but I'm not really sure how effective it is.
  • Only the most basic version of Sonja's time slow is implemented at all, and there is no practical difference between versions 2 and 3 of the rewind ability.
    • (Version 1 of the rewind, which freezes Sonja in place while everything else rewinds, is working somewhat as intended (aside from nothing except for Sonja's level timer rewinding) due to PF_FULLSTASIS being used to lock Sonja in place while C2 is held without Toss Flag or C1. Version 2 is intended to rewind Sonja along with all other mobjs, while Version 3 is intended to let her move around freely while everything else is rewound.)
  • The console command that is meant to disable Sonja's rewind in the event that the other players find being rewound to be more of a hindrance than a help is not implemented yet.
  • Sonja's counterattack is supposed to deal 2 damage, but I am not sure how to increase the damage dealt by the player attacking directly at all, let alone temporarily during one specific state.
    • (I suspect that I might be able to use a MobjMoveCollide hook.)
  • Sonja's radar and advance-warning passives have not been implemented yet.
    • I think the radar can draw from the automap that would otherwise be toggled with the Tab key in devmode, but Sonja's radar should only show what's within about 1200 fracunits of her current position and should be able to differentiate between different types of object (or at least between helpful and harmful objects).
  • Flora's spell sprites still need angled sprites and additional frames of animation.
  • Flora still needs her own Frost Shield sprites (Dirfex's Ice Shield is currently being used as a placeholder).
  • Several Badnik and boss abilities for Cassandra's Copy Bolt are not implemented yet.
    • In fact, I'm at somewhat of a loss for what abilities I can give Cassandra to emulate the behaviors and abilities of certain enemies, like Jet Jaw, Penguinator, or Crawla Commander.
    • There are other abilities where I have an idea of what I want Cassandra to do, but I'm not sure how to implement the powers. In particular, I'm not sure how to detect whether the top, bottom, front, or rear of Cassandra's hitbox has been hit for the Spring Shell, Banpyura, or Green Snapper abilities, how to stand on water for the Skim, how to launch the Crushtacean claw, how to emulate the burrowing of the Minus, how to drop projectiles downward for the Skim, Dragonbomber, or Jetty-Syn Bomber powers, or how to grant Cassandra a regenerating Lightning Shield or a charge-requiring hitscan attack if she copies Brak Eggman.
      • I may have figured out a system for detecting the top or bottom of the player's hurtbox, based on the relative z positions of the player and their attacker compared to the player's height parameter. I tested the Spring Shell power and it does seem to bounce Buzzes up and prevent damage as intended. I'm still not sure how I'm going to detect the player being attacked from the front, side, or back, though.
      • I figured out a system for emulating the Minus's burrowing that involves height manipulation and a ShouldDamage hook. I'm still not sure how I'm going to allow Cassandra to burrow underneath FOFs that are touching the ground beneath them.
      • I want Cassandra to be able to climb walls in a similar fashion to Samus's Spider Ball if she copies a Snailer, but I'm not sure how to check that the player is contacting a wall.
  • The ability for Cassandra to copy or mimic the abilities of other skins is not implemented yet.
    • (Well, technically, Cassandra can copy skins, but then I get an error about putting a string in a number variable. Also, even if that wasn't the case, the code to grant Cassandra the abilities of the copied skin is not written yet, because I'm not sure how to achieve my plan of partially overwriting Cassandra's code with the code of the copied skin.)
  • Cassandra's mimicry menu is not implemented yet.



Issues that need to be fixed:

  • The SOC PlayerText for each of these characters is way too long, to the point where it flat-out generates a warning message on character load for Cassandra.
  • Vixen Vortex doesn't put the user in the falling animation after it's done ascending, creating the erroneous impression that it can damage enemies and break monitors on the way down.
    • Vixen Vortex isn't intended to keep the user in the basic spinning animation while going up; it's supposed to play a vertically-twirling animation more akin to Blaze's tornado spin. (The double jump is called Vixen Vortex for a reason. Well, okay, the reason is that it also filled in for the Speed characters' tornado move in a hypothetical Sonic Heroes playable role for Annie…)
  • Holy Bolt and Copy Bolt hit 4 times per use, effectively bypassing their sub-standard damage per uncharged or low-charge shot. They're only supposed to hit once per shot. (And yes, I did write P_KillMobj code in their MobjMoveCollide hooks to deactivate them when they've hit something. I'm not quite sure why that isn't working. (Maybe I should make the source and inflictor nil rather than thing. Or maybe I should just use P_RemoveMobj instead.))
    • (I added code to temporarily remove MF_SHOOTABLE from enemies when Holy Bolt hits them, so hopefully that fixes this issue.)
      • (Nope, that didn't fix it!)
  • I can't quite figure out how to get GetSecSpecial to work. As a result, code that's intended to account for certain sector effects, like ring drain or CTF bases, only work properly with the intended sector effects by themselves, without any other sector effects being mixed in.
  • Annie hasn't been tested in multiplayer, so I have no idea whether or not her healing and revival abilities are even functional on other players.
  • Annie sometimes gets pushed out of the map when she withstands being crushed (and depending on the dimensions of the crusher and the map, being out-of-bounds doesn't always count as her continuing to be crushed, which can possibly force the player to manually restart from the pause menu). This happens far more often with sideways-moving crushers or continuously falling sectors.
  • Sonja's time slow outright freezes player.realtime instead of making it count up more slowly (slowedtime counts up at a rate of 1 per tic instead of the intended rate of 1 per 15 tics).
    • This issue has been fixed by reconfiguring the math.
  • When playing as Sonja, player.realtime continues counting up even after the PF_FINISHED player flag has been set, and doesn't stop incrementing until the results screen comes up.
    • I figured out a fix for this issue.
  • Sonja's flash step is still a bit finicky (it doesn't always move her in the direction the player is trying to move in) and could probably be implemented better. (In particular, I'd like for it to not activate if a movement key is already being held when Chrono Evasion negates damage; I'd like it to require a fresh button press so that the player can run through an attack or hazard without flash stepping.)
  • Sonja cannot properly store the mobj that attempted to hit her during Chrono Evasion, preventing her from initiating her counterattack.
  • Flora's Holy Flame doesn't break bustable walls. (I was able to use EV_CrumbleChain to let Cassandra's Minus ability smash bustable floors, so I'm not quite sure what I'm doing wrong.)
    • Flora's Holy Flame now breaks bustable FOFs, but it causes them to repeatedly crumble as long as the Holy Flame object that broke them lasts.
  • Flora's 2D Blue Splash isn't spawning icicles at all. (Also, I have a cart-behind-the-horse problem of calling variables before they're created, which obviously isn't working, but I'm not sure how else to prevent an object that already exists from being spawned. I think I may have solved that problem by setting up an icicle-counting variable instead, which I was inspired to try when I was writing the code for Cassandra's Unidus power, but I still need to figure out how to get it to actually spawn icicles.)
  • The obelisks created by Flora's Frost Shield aren't properly spreading out to surround Flora or self-destructing when the frostshieldactive variable hits 0.
    • I added nextstate = S_NULL to the death state. Hopefully that fixes this. (...Nope, not that simple...)
  • Flora's Icicle Blades is not spawning icicles at all. (This also prevents 3D Blue Splash from launching the icicles.)
  • I'm not sure how to make each Holy Lightning orb independently chase the closest shootable mobj, nor am I sure how to make it so that each orb can survive a single impact with a shootable mobj.
  • Flora's second Easter Egg Holy Lightning spin-off isn't behaving properly; the barrier orb dies the instant it covers her position, rather than floating around her and acting as a short-ranged enemy-destroying shield as intended.
  • Flora's Holy Barrier isn't blocking projectiles or enemies, nor is it slowing or stopping her movement while deployed or going away when Toss Flag is released.
    • Actually, Holy Barrier Wall blocks one projectile, then immediately dies. It doesn't deduct the projectile's damage from Flora's energy, either.
      • I reconfigured the ShouldDamage hook to more explicitly refer to the wall and dome by their variable names.
    • Holy Barrier Wall has no upkeep cost; it's supposed to continuously drain Flora's energy while it's active.
    • Holy Barrier Dome isn't able to be conjured at all.
  • Cassandra's Robo Hood abilities are rather finicky; the arrow's range is laughably short, and the backward and forward hops don't always move her in the intended direction.
    • I fixed the backwards hop weird direction issue with some help from @Monster Iestyn on Discord. Turns out I should have been multiplying by ANGLE_180 rather than using InvAngle.
  • Cassandra's Lance-a-Bot abilities are rather finicky; the main charge (C1) has very odd acceleration (this may be due to using P_Thrust), the secondary function that enables SF_DASHMODE (C2) doesn't seem to be working at all, I had to stick a cooldown onto the dash mode toggle in order to get it to work properly without being impossible to manually deactivate, and the power overall doesn't seem to reliably damage enemies, smash spikes, or protect Cassandra from damage, even when she's above the intended speed threshold (as indicated by the ghost mobjs). (Maybe I should be tracking something other than player.speed.)
    • I'd like Cassandra to play the Lance-a-Bot charge sound when she reaches the speed threshold (I added sfx_zoom, the AttackSound of MT_FACESTABBER according to the wiki, but I don't quite know if that's the right choice), and emit the Lance-a-Bot charging shockwaves while moving at or faster than the designated charging speed. Considering that there's a dashmode option as an alternative and more controllable means of going fast, the Lance-a-Bot shockwaves would be a more reliable indicator of moving fast enough to shrug off damage and smash walls and spikes anyways.
  • Cassandra gets constantly jostled around by her own followitem when copying an Egg Guard. (I did try designating her as the followitem's target, but this seems to have returned an error.) (I may have fixed that by setting up an alternative means of having the Egg Guard shield follow her around. (Actually, yes, that did fix the issue, but now the shield dies immediately on spawning.))
  • The minusdigging variable for the Minus power doesn't seem to be working as intended; it doesn't seem to be draining energy when it should be on, allowing energy regeneration when it should be off, or modifying Cassandra's height at the appropriate times. Cassandra also doesn't pop up when C1 is released.
  • Some of the enemy-based objects that Cassandra can spawn behave in weird ways, like the Sea Egg shockwave only spawning one little lightning bolt that quickly vanishes.
    • I fixed the Sea Egg shockwave by adding a for loop that shoots 360 projectiles — one for each angle. (The quick vanishing was a result of me accidentally deactivating MF_NOGRAVITY.]
  • Cassandra gets hurt by some of her own projectiles, including Dragonbomber mines and Brak Eggman's flamethrower, despite Cassandra being designated as the target and MF_PAIN being turned off. (I actually had to spawn the mines over 40 fracunits away from Cassandra and add SH_PROTECTFIRE to the Lightning Shield that Cassandra gets by copying Brak Eggman to test the mines and flamethrower without constantly hurting Cassandra. I did eventually fix the flamethrower by using a MobjMoveCollide hook to make the game ignore collisions between Cassandra and her own flames.)
  • Some of Cassandra's copy ability objects, like the Unidus spikeballs, don't despawn when the ability is discarded.
  • Cassandra's dive/surface ability gained by copying the Sea Egg gets her stuck in the ceiling.
  • The timer that Cassandra gets to regulate her regenerating Lightning Shield in Brak Eggman mimicry isn't working right. While she should immediately get the shield upon copying Brak Eggman if she has enough energy to activate it, once she loses it, she should have to wait 25 seconds to get it back (much like Brak Eggman takes about 25 seconds to regenerate his own electric barrier). Currently, the variable that is meant to store whether or not the shield is ready to activate in the event that Cassandra doesn't have enough energy to activate it when the timer runs down (so it can be reactivated as soon as it has enough energy) is toggling on while Cassandra currently has a shield, resulting in her getting a new shield the instant she takes damage.
    • Cassandra's supposed to have the Brak Eggman electric barrier as a followitem while she has her Brak Eggman Lightning Shield, but it doesn't show up for some reason.
  • Some copy abilities, like Unidus's spikeball launch, Egg Mobile's laser shots, and Brak Eggman's sniper shot and missiles, don't seem to be working at all.
 

Attachments

  • SRB2 Addon Ideas - The Belnades Sisters (Advanced Commentary).pdf
    438 KB · Views: 74
  • SRB2 Addon Ideas - The Belnades Sisters.pdf
    361.1 KB · Views: 65
  • Spriting Guidelines for the Belnades Sisters.pdf
    953.4 KB · Views: 61
  • CL_Annie-Belnades.pk3
    1.8 MB · Views: 52
  • CL_Cassandra-Belnades.pk3
    2.1 MB · Views: 44
  • CL_Flora-Belnades.pk3
    1.8 MB · Views: 45
  • CL_Sonja-Belnades.pk3
    1.8 MB · Views: 46
Last edited:
  • Cool!
Reactions: Dee
So, uh, is this thread going to get any more attention? I'd like to show off some of the more problematic code I've got in more detail (without requiring people to download the .pk3s), but I don't want to do that without anyone else having made posts in between, if only so that the mods don't have cause to merge two very large posts together into an awful jumbled mess. (Let's just say that I used to be quite active on the Smashboards, which uses the same message board engine as this site, and I still remember being yelled at for making seven posts in a row over there several years ago. I can't hyperlink that thread here because it's a non-SRB2 site, I know the mods will have to approve any post with foreign links, the mods will have cause to merge this with my opening post since nobody else posted anything in between, and I'd like to be able to continue updating the opening post as existing issues get resolved and new issues come up. But rest assured that I've seen what happens when multiple very large posts get merged together on a message board like this one, and it's not pretty.)
 
Here's a tip:
When you need to write a lot of information, instead of writing it all in a post, write it in a text file, and upload it.
That way, people don't need to scroll through it every time they look at this thread.
Things like the bullet lists you wrote could be an example of such a time to use a text file.

Anyway, I like the concept of these guys, curious to see how they'll end up.
 
Here's a tip:
When you need to write a lot of information, instead of writing it all in a post, write it in a text file, and upload it.
That way, people don't need to scroll through it every time they look at this thread.
Things like the bullet lists you wrote could be an example of such a time to use a text file.

Anyway, I like the concept of these guys, curious to see how they'll end up.
I have text files for some of the bigger pieces of code, I just think that it's easier for everyone to not be constantly removing and reuploading files to my posts if editing the content of the posts themselves will suffice.
Post automatically merged:

In fact, let me just attach some of those text files for some of the code I'm having trouble with, namely Annie's respawn procedure tweaks, Sonja's Chrono Evasion, and Flora's... almost everything with her spells.
Post automatically merged:

Here's my code for Sonja's time slow. As I said in the first post, I still need to include code that will freeze every mobj (other than Sonja), FOF, scroller, pusher, and polyobject for 1 tic every 15 tics or something along those lines in order to achieve the effect of slowing the game down; the reason I haven't done that yet is because I'm not sure how. But right now, my issue is the slowedtime variable counting up too quickly.

Time Slow:
//Slow Time (Code to slow down everything but Sonja on command)
--Basic time slow
addHook("PlayerThink", function(player)
    if player.mo and player.mo.valid then
  
        if player.mo.skin ~= "sonja_belnades" 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.slowedtime == nil then
            player.slowedtime = 0
        end
      
        if player.custom1down > 1
        and player.custom2down == 0
        and player.mo.energy >= 3*FRACUNIT then
            if not (player.custom1down%TICRATE) then
                player.mo.energy = $ - 3*FRACUNIT --reduce energy by 3
            end
            if (player.custom1down%(1*(TICRATE/15))) then
                player.slowedtime = $ + 1
            end
        end
    end
end)

The idea is for slowedtime to increase by 1 for every 15th of a second that C1 is held down. (Come to think of it, maybe I could just replace 1*(TICRATE/15) with 15. But I was previously using if (player.custom1down%(TICRATE*15)) and that might as well have been if (player.custom1down%TICRATE) as far as how often slowedtime incremented.



Here's the code to make Sonja's realtime be affected by her time manipulation. (Trying to tweak player.realtime directly with the time slow code (e.g. if (player.custom1down%(TICRATE*15)) then player.realtime = $ - 1) accomplished nothing, and trying to modify leveltime was flat-out disallowed by the game (I got a warning message in the console about it).)

Time Tomfoolery:
//Time manipulation affecting the player's level time
addHook("PlayerThink", function(player)
    if player.mo and player.mo.valid then
  
        if player.mo.skin ~= "sonja_belnades" then
            return
        end
      
        if (gametype == GT_RACE or gametype == GT_COMPETITION) then
            player.realtime = leveltime - (player.slowedtime + player.rewoundtime + (4*TICRATE)) --allow Sonja's time slow and rewind to modify her level timer
            if player.pflags & PF_FINISHED then
                stoppedclock = true
//                player.realtime = player.realtime --stop timer from changing when level is completed
            end
        else
            player.realtime = leveltime - (player.slowedtime + player.rewoundtime) --allow Sonja's time slow and rewind to modify her level timer
            if player.pflags & PF_FINISHED then
                stoppedclock = true
//                player.realtime = player.realtime --stop timer from changing when level is completed
            end
        end
      
        if player.tossflagdown == 1 --If Toss Flag is pressed on its own
        and player.custom1down == 0 --Toss Flag is also used to modify Time Slow and Rewind, so this print command can't be used during time manipulation
        and player.custom2down == 0
        and player.gotflag == 0 then --Don't overwrite Toss Flag's default function
            print("Full leveltime (tics) = "..leveltime)
            print("Adjusted leveltime (tics) = "..player.realtime)
            print("Difference in leveltime (tics) = "..(leveltime - player.realtime))
            print("Full leveltime (seconds) = "..G_TicsToHours(leveltime)..":"..G_TicsToMinutes(leveltime, false)..":"..G_TicsToSeconds(leveltime)..":"..G_TicsToCentiseconds(leveltime))
            print("Adjusted leveltime (seconds) = "..G_TicsToHours(player.realtime)..":"..G_TicsToMinutes(player.realtime, false)..":"..G_TicsToSeconds(player.realtime)..":"..G_TicsToCentiseconds(player.realtime))
            print("Difference in leveltime (seconds) = "..G_TicsToHours((leveltime - player.realtime))..":"..G_TicsToMinutes((leveltime - player.realtime), false)..":"..G_TicsToSeconds((leveltime - player.realtime))..":"..G_TicsToCentiseconds((leveltime - player.realtime))) --Allow the player to see how much they've modified the leveltime
            chatprint("Full leveltime (tics) = "..leveltime, false)
            chatprint("Adjusted leveltime (tics) = "..player.realtime, false)
            chatprint("Difference in leveltime (tics) = "..(leveltime - player.realtime), false)
            chatprint("Full leveltime (seconds) = "..G_TicsToHours(leveltime)..":"..G_TicsToMinutes(leveltime, false)..":"..G_TicsToSeconds(leveltime)..":"..G_TicsToCentiseconds(leveltime), false)
            chatprint("Adjusted leveltime (seconds) = "..G_TicsToHours(player.realtime)..":"..G_TicsToMinutes(player.realtime, false)..":"..G_TicsToSeconds(player.realtime)..":"..G_TicsToCentiseconds(player.realtime), false)
            chatprint("Difference in leveltime (seconds) = "..G_TicsToHours((leveltime - player.realtime))..":"..G_TicsToMinutes((leveltime - player.realtime), false)..":"..G_TicsToSeconds((leveltime - player.realtime))..":"..G_TicsToCentiseconds((leveltime - player.realtime)), false) --Show everyone else how much the leveltime has been tweaked, too
        end
    end
end)

addHook("PlayerSpawn", function(player)
    if player.mo and player.mo.valid then
  
        if player.mo.skin ~= "sonja_belnades" then
            return
        else
            player.slowedtime = 0
            player.rewoundtime = 0 --Manipulated time doesn't carry over between maps
        end
    end
end)

This is actually working as intended, except for the part where player.realtime doesn't stop increasing when the level is finished (and I'd like to prevent Sonja's abilities from decreasing player.realtime when the level is done, too, so that she can't reduce her timer after finishing in the event that other players in co-op or a race haven't finished yet). I'm also not happy with Sonja losing her accumulated time reduction if she dies and respawns in the middle of a map, but I don't know if the time manipulation reset hook will work as intended if I change it from a PlayerSpawn hook to a MapChange hook.
 

Attachments

  • Annie - Revive.txt
    14 KB · Views: 52
  • Flora - 2D Blue Splash v2.txt
    9.6 KB · Views: 46
  • Sonja - Chrono Evasion v4.6.txt
    4.4 KB · Views: 53
  • LUA_FLORAABILITIES.txt
    57.7 KB · Views: 51
Last edited:
Okay, seriously, what is up with Cassandra frying herself with her own flamethrower?! (And why does the message board refuse to accept gifs?)

Cassandra's Brak Eggman flamethrower:
if player.custom1down > 1
and player.custom2down == 0
and player.mo.energy >= 5*FRACUNIT then
    if player.custom1down == 2 then
        player.mo.energy = $ - 5*FRACUNIT
    end
    if player.custom1down > 40 then
        if not (leveltime%TICRATE) then
            player.mo.energy = $ - 5
        end
    end
    if (player.custom1down%5) then
        local brakflame = P_SpawnPlayerMissile(player.mo, MT_CYBRAKDEMON_FLAMESHOT, 0) --flamethrower
        brakflame.target = player.mo
    end
    if brakflame and brakflame.valid then --if the player is shooting flames
        player.mo.copypoweruse = 1
    else
        if player.mo.braksnipeprep == 0 then --if the player isn't sniping
            player.mo.copypoweruse = 0
        end
    end
end
Post automatically merged:

And why won't the missiles fire? Seriously, I checked with a Fire Flower, and I do have my Fire key bound.

Cassandra's Brak Eggman missiles:
if (player.cmd.buttons & BT_ATTACK) == 1
and player.custom3down == 0
//and (G_RingSlingerGametype() == false or ((player.powers[pw_infinityring] == 0 and player.powers[pw_automaticring] == 0 and player.powers[pw_bouncering] == 0 and player.powers[pw_scatterring] == 0 and player.powers[pw_grenadering] == 0 and player.powers[pw_explosionring] == 0 and player.powers[pw_railring] == 0) or player.rings == 0)) --and the player can't shoot any Ringslinger rings
and player.mo.energy >= 25*FRACUNIT/2
and player.mo.brakmissilecooldown == 0 then
    player.mo.energy = $ - 25*FRACUNIT/2
    P_SpawnPlayerMissile(player.mo, MT_CYBRAKDEMON_MISSILE, 0)
    player.mo.brakmissilecooldown = 3*TICRATE/4
end
if player.custom1down > 1
and player.custom2down > 1
and player.custom1down > player.custom2down
and player.mo.energy >= 1*FRACUNIT then
    if player.custom2down == 2 then
        player.mo.energy = $ - 1*FRACUNIT
    end
    if player.custom2down > 40 then
        if not (leveltime%TICRATE) then
            player.mo.energy = $ - 1*FRACUNIT
        end
    end
    if (player.custom1down%5) then
        local brakgoop = P_SpawnPlayerMissile(player.mo, MT_BLACKEGGMAN_GOOPFIRE, 0) --goop spray
        brakgoop.target = player.mo
    end
    if brakgoop and brakgoop.valid then --if the player is firing goop
        player.mo.copypoweruse = 1
    else
        if player.mo.braksnipeprep == 0 then --if the player isn't sniping
            player.mo.copypoweruse = 0
        end
    end
end
if player.custom3down > 1
and (player.cmd.buttons & BT_ATTACK) == 1
and player.custom3down > (player.cmd.buttons & BT_ATTACK)
//and (G_RingSlingerGametype() == false or ((player.powers[pw_infinityring] == 0 and player.powers[pw_automaticring] == 0 and player.powers[pw_bouncering] == 0 and player.powers[pw_scatterring] == 0 and player.powers[pw_grenadering] == 0 and player.powers[pw_explosionring] == 0 and player.powers[pw_railring] == 0) or player.rings == 0)) --and the player can't shoot any Ringslinger rings
and player.mo.energy >= 15*FRACUNIT
and player.mo.brakmissilecooldown == 0 then
    player.mo.energy = $ - 15*FRACUNIT
    P_SpawnPlayerMissile(player.mo, MT_BLACKEGGMAN_MISSILE, 0)
    player.mo.brakmissilecooldown = 3*TICRATE/2
end
Post automatically merged:

What the heck. Even after I wrote in a pseudo-pain state, Holy Bolt is still hitting multiple times per shot. I don't get it.
Post automatically merged:

For that matter, I reorganized Flora's code to put 3D Blue Splash in a single hook so that its local variables can actually communicate, and it's still not working. The 2D version isn't working, either.
 

Attachments

  • Holy Bolt (Annie).txt
    16.8 KB · Views: 47
  • LUA_FLORAABILITIES.txt
    61.1 KB · Views: 48
Last edited:
Ugh, this thread really needs more attention. I have a lot of issues that I need to get fixed!



I managed to get the missiles working by adding a firedown variable. Part of the problem with the snipe was messing up the custom3down variable, but it's still not fully functional.
Post automatically merged:

The timer that Cassandra gets to regulate her regenerating Lightning Shield in Brak Eggman mimicry isn't working right. While she should immediately get the shield upon copying Brak Eggman if she has enough energy to activate it, once she loses it, she should have to wait 25 seconds to get it back (much like Brak Eggman takes about 25 seconds to regenerate his own electric barrier). Currently, the variable that is meant to store whether or not the shield is ready to activate in the event that Cassandra doesn't have enough energy to activate it when the timer runs down (so it can be reactivated as soon as it has enough energy) is toggling on while Cassandra currently has a shield, resulting in her getting a new shield the instant she takes damage. Also, Cassandra's supposed to have the Brak Eggman electric barrier as a followitem while she has her Brak Eggman Lightning Shield, but it doesn't show up for some reason.
 
Last edited:
This is not supposed to be what happens by default when Cassandra presses C3 while copying the Sea Egg after diving into one of the tunnels in the floor of DSZ3...

srb20507.png
srb20510.png

Post automatically merged:

I think I've finally got the Brak Eggman sniper shot working. The A_CapeChase part with the reticule is still returning errors and I'm not quite sure why, outside of objects that are already defined in SRB2's base code not working well with receiving local variables upon being spawned (but I attach local variables to already-existing objects in several other parts of Cassandra's copy power code without apparent issues). But the rest of the snipe is working mostly as intended.

Brak Eggman Sniper Shot:
if player.custom3down == 1
//and player.mo.braksnipeprep == 0
and player.firedown == 0
and player.mo.energy >= 10*FRACUNIT then
    player.braksnipetarget = P_LookForEnemies(player, false, true) --find a sniping target
    //player.braksnipetarget = A_FindTarget(player.mo, ((MF_SHOOTABLE)), 0)
    if (player.braksnipetarget and player.braksnipetarget.valid) then --if a target was found
        if P_CheckSight(player.mo, player.braksnipetarget) == true then --if the player has line of sight
            player.mo.braksnipeprep = $ + 1 --start preparing the sniper shot
            print("Locked on to "..player.braksnipetarget.."! Keep them in your sights to deal guaranteed damage!")
            //print("Locked on to the target! Keep them in your sights to deal guaranteed damage!")
            S_StartSound(player.mo, sfx_s3k9d, nil)
            local reticule = P_SpawnMobjFromMobj(player.braksnipetarget, 0, 0, (player.braksnipetarget.height / 2), MT_CYBRAKDEMON_TARGET_RETICULE)
            reticule.target = player.braksnipetarget
            player.mo.energy = $ - 1*FRACUNIT
        end
    end
end
if player.custom3down == 0 then
    player.mo.braksnipeprep = 0 --reset snipe if C3 is released
end
if player.custom3down > 1
and player.firedown == 0
and player.mo.braksnipeprep >= 1
//and player.custom3down == player.mo.braksnipeprep
//and player.custom3down =< 5*TICRATE
and player.mo.braksnipeprep < 5*TICRATE
and player.mo.energy >= (9*FRACUNIT - (((player.mo.braksnipeprep*TICRATE)*FRACUNIT/4)>>TICRATE)) then
    if (player.braksnipetarget and player.braksnipetarget.valid) then
    //and (reticule and reticule.valid) then
        if P_CheckSight(player.mo, player.braksnipetarget) == true then --if the player maintains line of sight
            player.mo.braksnipeprep = $ + 1
            player.mo.copypoweruse = 1
            A_CapeChase(reticule, (player.braksnipetarget.height / 2)+0, 0+0)
            if player.mo.braksnipeprep == 1*TICRATE or player.mo.braksnipeprep == 2*TICRATE or player.mo.braksnipeprep == 3*TICRATE or player.mo.braksnipeprep == 4*TICRATE then
                player.mo.energy = $ - 1*FRACUNIT/4
                S_StartSound(player.mo, sfx_s3k9d, nil)
                print("Lock-on maintained!")
            end
        else --if line of sight is broken
            player.mo.braksnipeprep = 0
            player.mo.copypoweruse = 0
            if (reticule and reticule.valid) then
                P_KillMobj(reticule, nil, nil)
            end
            player.braksnipetarget = 0
            print("You broke line of sight! Your sniper shot is ruined!")
        end
    else
        print("...Wait, did you just destroy the target before shooting it?!")
        player.mo.braksnipeprep = 0
        player.mo.copypoweruse = 0
        if reticule and reticule.valid then
            P_KillMobj(reticule, nil, nil)
        else
            print("WHAT? How did you screw up that badly...?!?")
        end
        player.braksnipetarget = 0
    end
end
if player.custom3down >= 5*TICRATE
and player.firedown == 0
and player.mo.braksnipeprep == 5*TICRATE
and player.mo.energy >= 8*FRACUNIT then
    if (player.braksnipetarget and player.braksnipetarget.valid) then
    //and (reticule and reticule.valid) then
        if P_CheckSight(player.mo, player.braksnipetarget) == true then --if the player maintains line of sight
            P_DamageMobj(player.braksnipetarget, reticule, player.mo, 2) --snipe the target
            player.mo.energy = $ - 8*FRACUNIT
            S_StartSound(player.mo, s3kb4, nil)
            player.mo.copypoweruse = 0
            player.mo.braksnipeprep = 0
            if (reticule and reticule.valid) then
                P_KillMobj(reticule, nil, nil)
            end
            print(player.braksnipetarget.." successfully sniped!")
            //print("Target successfully sniped!")
            player.braksnipetarget = 0
        else --if line of sight is broken
            player.mo.braksnipeprep = 0
            player.mo.copypoweruse = 0
            if (reticule and reticule.valid) then
                P_KillMobj(reticule, nil, nil)
            end
            player.braksnipetarget = 0
            print("You broke line of sight! Your sniper shot is ruined!")
        end
    else
        print("...Wait, did you just destroy the target before shooting it?!")
        player.mo.braksnipeprep = 0
        player.mo.copypoweruse = 0
        if reticule and reticule.valid then
            P_KillMobj(reticule, nil, nil)
        else
            print("WHAT? How did you screw up that badly...?!?")
        end
        player.braksnipetarget = 0
    end
end
if player.mo.braksnipeprep > 0
and player.firedown == 1 then
    player.mo.braksnipeprep = 0
    if reticule and reticule.valid then
        P_KillMobj(reticule, nil, nil)
    end
    player.mo.copypoweruse = 0
    player.braksnipetarget = 0
    print("You can't snipe with a bazooka!")
end
if player.custom3down > 1
and player.mo.braksnipeprep == 0 then
    player.mo.copypoweruse = 0 --resume energy regeneration
end



On a related note of things not working correctly, for the Egg Mobile power, I've given Cassandra the standard "hold Custom button to activate MF_NOGRAVITY, then press and hold Jump to ascend or Spin to descend" flight mode that she has for most flying enemies (Buzz, BASH, Pyre Fly, Dragonbomber, and both Jetty-syn versions, among others (well, okay, the Jetty-syns aren't implemented yet)), three laser attacks based on what buttons she presses and whether or not she's using the flight mode, and a spikeball summon. None of the laser attacks are working for some reason…

(And before you ask — no, I have no plans to release the independent Buzz flight code, because it'd be broken as fuck without an energy meter to regulate it.)
 

Attachments

  • Buzz Flight.txt
    1.2 KB · Views: 49
  • Cassandra - Boss Copy Abilities.txt
    28.4 KB · Views: 51
  • Cassandra - Badnik Copy Abilities.txt
    74.8 KB · Views: 50
  • L_Buzz-Flight.wad
    1.9 KB · Views: 60
Last edited:
Sonja's time slow is causing a ton of slowdown… by which I mean it's actually tanking the frame rate.
 
Last edited:
Ugh, I can't seem to figure out what I'm doing wrong with Holy Flame's FOF-smashing code.
 

Attachments

  • Flora - Holy Flame v1.txt
    5.5 KB · Views: 54
Ever considered looking for help at the SRB2 Discord? You might find someone willing to help there.
 
I see, carry on.

I may still need to ask for help with bigger and more nebulous problems (like finding out what the hell is wrong with Flora's Blue Splash and Holy Barrier) here in order to not risk getting kicked out of the Discord server again…
 
wow im literally a skeleton, i had to read all of that 💀
anyways wow very complex mod no way 🗣️🗣️🔥🔥🗣️🔥🔥🗣️🔥🔥🔥🔥🔥🗣️🗣️
 
Recently got Flora's Holy Flame patched up. Right now, I'm trying to figure out how to get the game to treat the surface of water as ground that a character can stand on for the purpose of Cassandra's Skim ability. Well, that and getting Annie's respawn procedure modifications working.
 

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

Back
Top