1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Need an Opinion, Monster Useless When Stood On

Discussion in 'Scripts' started by greatguys1, Nov 3, 2017.

  1. greatguys1

    greatguys1 New Adventurer Developer Warriors of the North

    162
    3
    Apr 20, 2013
    Yes
    I've been working on a monster mostly in the last couple of days, however, I found a fatal flaw with it. You can probably guess by the title, but before I explain, I should note that the gimmick of this monster is that they're most effective in groups. While one can hardly do anything, 5+ can be deadly when all are attacking one thing. When you stand on them however, only one is able to attack you at a time, due to the range of the attacks and the enemies bboxes blocking each other. Sometimes one can't even manage to attack you. Increasing the range of the attacks doesn't help at all. They have a tendency to stand on each other, but the problem persists even when changing the bboxes so they can't stand on each other. The scripts in case you need 'em, only these two are required for it to run. Sounds will probably only work in the alpha build because of $get_random_token(). You will need this model in order for this script to work:
    https://www.dropbox.com/s/lgc4q7crntkwhl0/chumtoad.mdl?dl=1
    Put in msc/models/monsters.

    Chumtoad:
    Code:
    //Chumtoad by greatguys1
    //This doens't follow the original concept of it from hl1 what-so-ever.
    //The idea is to have it like "zerg" where they're most effective in numbers, having damage scale higher the more it attacks, and even more when more are attacking the same target.
    
    #scope server
    
    {
        //Settings for base monster new
        setvar ANIM_RUN "hop_1"
        setvar ANIM_WALK "hop_1"
        setvar ANIM_IDLE "idle"
        setvard ANIM_ATTACK "flinch2"
    
        setvard NPC_NO_ATTACK 0
       
        setvard ATTACK_MOVERANGE 10
        setvard ATTACK_RANGE 50
        setvard ATTACK_HITRANGE 60
        const ATTACK_HITCHANCE 80
    
        const FLEE_HEALTH 0
        const FLEE_CHANCE 0
    
        setvard CANT_FLEE 1
        setvard CAN_RETALIATE 1
        setvard CAN_FLINCH 0
    
        //damage_stack_mult
        const STACK_DAMAGE_SCRIPT "test_scripts/damage_stack_mult"
        const STACK_PARAM2 5
        const STACK_PARAM3 0.1
        const STACK_PARAM4 10
    
        //Custom Blink cycle //If anyone wants to add a blink cycle to the other skins, I'll gladly accomondate it here
        const BLINK_FREQ 5
        const BLINK_DUR 0.2 //For each step
        setvard BLINK_STEP 0
        const BLINK_MAX 2 //Two other than the idle, eye open state.
        setvard BLINK_CYCLE 1 //1 for up, -1 for down
    
        //Suicide chances
        const SUICIDE_CHANCE 100 //% chance
        const SUICIDE_THRESHOLD 0.7 //Multiplier of what health I need to be under before I check against chance to explode
        const SUICIDE_DISTANCE 100 //Distance affected by explosion
        setvard SUICIDING 0
        setvard TRIED_SUICIDE 0
    
        //Other stuff particular to this script
        const ANIM_CHARGE "idle2"
        const ANIM_SUICIDE "flinch1"
        setvard ANIM_IDLE3_CHANCE 5 //% chance to use the idle3 animation, slower but more damage
        const LONG_ATTACK $rand(50,60) //Not long range, but taking longer to strike.
        const SHORT_ATTACK $rand(10,20)
    
        const MONSTER_HEALTH $get(ent_me,maxhp) //I think this'll grab it again should it change.
    
        const GIB_BURSTER_SCRIPT "effects/sfx_gib_burst_alien"
        const GIB_BURSTER_FORCE 300
    
        const EXPLOSION_SFX "effects/sfx_sprite"
        const EXPLOSION_SPRITE "oculus/exp_green.spr"
        const EXPLOSION_SFX_SOUND "monsters/tube/Tube_ExplodingDeath.wav"
    
        const DEATH_SOUNDS "monsters/bat/pain1.wav;monsters/bat/pain2.wav;monsters/beetle/idle.wav2;monsters/beetle/idle3.wav"
        const IDLE_SOUNDS "monsters/ogre_welp/bc_idle2.wav;monsters/ogre_welp/bc_idle3.wav;monsters/ogre_welp/bc_idle4.wav"
    
        const PAIN_SOUNDS "monsters/ogre_welp/bc_pain1.wav;monsters/ogre_welp/bc_pain2.wav;monsters/ogre_welp/bc_pain3.wav"
        const PAIN_SOUND_RATE 100 //percent chance to play pain sound
    
        const HIT_SOUNDS "monsters/tube/TubeCritter_Hit1.wav;monsters/tube/TuberCritter_Hit2.wav;monsters/tube/TubeCritter_Hit3.wav"
        const HIT_SOUND_RATE 100 //percent chance to play hit sound
    }
    
    #include monsters/base_monster_new
    #include test_scripts/monster_explode
    
    { game_precache
    
        precache monsters/chumtoad.mdl
        precache EXPLOSION_SPRITE
        precache agibs.mdl
    }
    
    { npc_spawn
    
        name "a|Chumtoad"
        race vermin
        hp 300
        setmodel "monsters/chumtoad.mdl"
        width 20
        height 20
        setmoveanim ANIM_RUN
        setidleanim ANIM_IDLE
        blood green
        roam 0
    
        //setvard MONSTER_HEALTH $get(ent_me,hp)
        setvard SOUND_CHANNEL $rand(0,100) //I dunno what the max is
    
        callevent BLINK_FREQ do_blinking
    }
    
    //{ cycle_down
    
    //    playanim loop ANIM_IDLE
    //}
    
    { do_blinking
    
        local L_PROPS $get(ent_me,renderprops)
        local L_SKIN $get_token(L_PROPS,4)
    
        setvard BLINK_STEP $math(add,BLINK_STEP,BLINK_CYCLE)
    
        if ( BLINK_STEP >= BLINK_MAX )
        {
            setvard BLINK_CYCLE -1
        }
        else if ( BLINK_STEP <= 0 )
        {
            setvard BLINK_CYCLE 1
        }
    
        if ( L_SKIN < 3 )
        {
            setprop ent_me skin BLINK_STEP
        }
    
        if ( BLINK_STEP == 0 )
        {
            callevent BLINK_FREQ do_blinking
        }
        else
        {
            callevent BLINK_DUR do_blinking
        }
    }
    
    { game_damaged
    
        local L_HP $get(ent_me,hp)
    
        if ( L_HP <= $math(multiply,MONSTER_HEALTH,SUICIDE_THRESHOLD) )
        {
            if ( !TRIED_SUICIDE )
            {
                setvard TRIED_SUICIDE 1
    
                if ( $func(func_test_chance,SUICIDE_CHANCE) )
                {
                    callevent do_suicide_charge
                }
            }
        }
    
        if ( $func(func_test_chance,PAIN_SOUND_RATE) )
        {
            playsound SOUND_CHANNEL 10 $get_random_token(PAIN_SOUNDS)
        }
    
        return **clear
        returndata 1 //A bug exists that a $func within one of these functions will overwrite the returndata. Resetting it.
    }
    
    { game_damaged_other //PARAM1=target_hit PARAM2=dmg PARAM3=dmg_type //items return <attack_callback>_damaged_other
    
        local L_TARGET PARAM1
        applyeffect L_TARGET STACK_DAMAGE_SCRIPT $get(ent_me,name) STACK_PARAM2 STACK_PARAM3 STACK_PARAM4
    
        if ( $func(func_test_chance,HIT_SOUND_RATE) )
        {
            playsound SOUND_CHANNEL 10 $get_random_token(HIT_SOUNDS)
        }
    
        return **clear
        returndata 1 //A bug exists that a $func within one of these functions will overwrite the returndata. Resetting it.
    }
    
    { game_death
    
        playsound SOUND_CHANNEL 10 $get_random_token(DEATH_SOUNDS)
    }
    
    { do_suicide_charge
    
        callevent npcatk_suspend_ai
        playanim critical ANIM_CHARGE
        setvard SUICIDING 1
    }
    
    { finish_charge //Called from the model
    
        playanim critical ANIM_SUICIDE
    }
    
    { finish_suicide //Called from the model
    
        setprop ent_me rendermode 5
        setprop ent_me renderamt 0
    
        callevent do_explode
        callevent npc_suicide
    }
    
    { do_explode
    
        local L_VEC $get(ent_me,origin)
        vectoradd L_VEC $vec(0,0,30)
    
        local L_COL $clcol(0,0,0)
        local L_STR "0;3;255;add;"
        stradd L_STR L_COL
        stradd L_STR ";20;10"
    
        clientevent new all EXPLOSION_SFX L_VEC EXPLOSION_SPRITE L_STR 0.5
        clientevent new all GIB_BURSTER_SCRIPT L_VEC GIB_BURSTER_FORCE
        playsound 0 10 EXPLOSION_SFX_SOUND
    }
    
    { npc_selectattack
    
        if ( $rand(0,100) <= ANIM_IDLE3_CHANCE )
        {
            setvard ANIM_ATTACK idle3
        }
        else
        {
            setvard ANIM_ATTACK flinch2
        }
    }
    
    { attack_1 //Called from the model
    
        callevent npcatk_dodamage NPCATK_TARGET ATTACK_HITRANGE LONG_ATTACK ATTACK_HITCHANCE pierce
    }
    
    { attack_2 //Called from the model
    
        callevent npcatk_dodamage NPCATK_TARGET ATTACK_HITRANGE SHORT_ATTACK ATTACK_HITCHANCE pierce
    }
    
    { func_test_chance //Returns 1 on a win, 0 on fail. PARAM1 = % to win
    
        local L_CHANCE PARAM1
        local L_ROLL $rand(1,100)
    
        if ( L_ROLL <= L_CHANCE )
        {
            return 1
        }
        else
        {
            return 0
        }
    }
    Attack Multiplier Stacker:
    Code:
    //Increasing damage from the same monster / same type of monster via a multiplier. Originally built for the chumtoad. By greatguys1
    //If you can think of a better name that best describes what this does, please change it, as the current name is inaccurate/confusing.
    //I'm not using the effect_base as it doesn't seem to have anything that would pertain to this.
    
    //Accepts params:
    //1; Creature name
    //2; Expire time
    //3; multiplier increment factor
    //4; max multiplier
    
    #scope server
    
    {
        const CHECK_STACK_TIME 1 //Will always check at one second increments
    
        setvard CUR_MULT 1
        setvard ACTIVATED 0
        setvard DAMAGED_THIS_TICK 0
        setvard TICKS_NOT_DAMAGED 0
    }
    
    { game_precache
    
        local L_ID "stack_damage"
    
        setvard reg.effect.name L_ID
        setvard reg.effect.id L_ID
        setvard reg.effect.flags "nostack"
        setvard reg.effect.script $currentscript
        setvard game.effect.removeondeath 1
        setvard game.effect.id L_ID
        setvard game.effect.displayname "Zerg Swarm Debuff"
        setvard game.effect.flags "nostack"
        setvard game.effect.type "nostack"
    
        registereffect
    }
    
    { game_activate //PARAM1 = creature name, not full PARAM2 = expire time
    
        setvard CREATURE_STACK_NAME PARAM1
        setvard EXPIRE_TIME PARAM2
        setvard INCREMENT_FACTOR PARAM3
        setvard MAX_MULT PARAM4
    
        setvard ACTIVATED 1
        callevent check_stack
    }
    
    { check_stack
    
        if ( ACTIVATED )
        {
            if ( !DAMAGED_THIS_FRAME )
            {
                setvard TICKS_NOT_DAMAGED $math(add,TICKS_NOT_DAMAGED,1)
                if ( TICKS_NOT_DAMAGED == EXPIRE_TIME )
                {
                    callevent effect_die
                }
            }
            else
            {
                setvard TICKS_NOT_DAMAGED 0
                setvard DAMAGED_THIS_FRAME 0
            }
        }
    
        callevent CHECK_STACK_TIME check_stack
    }
    
    { game_damaged //PARAM1=attacker PARAM2=dmg PARAM3=dmg_type PARAM4=accuracy_roll PARAM5=skill PARAM6=Inflicter
    
        if ( ACTIVATED )
        {
            local L_ATTACKER PARAM1
    
            if ( CREATURE_STACK_NAME contains $get(L_ATTACKER,name) )
            {
                local L_DAMAGE PARAM2
                setvard CUR_MULT $math(add,CUR_MULT,INCREMENT_FACTOR)
               
                if ( CUR_MULT > MAX_MULT ) //I can't find the clamp command
                {
                    setvard CUR_MULT MAX_MULT
                }
    
                local L_DAMAGE $math(multiply,L_DAMAGE,CUR_MULT)
    
                returndata CUR_MULT
                //setdmg dmg L_DAMAGE
                setvard DAMAGED_THIS_FRAME 1
            }
        }
    }
    
    { game_death
    
        callevent effect_die
    }
    
    { effect_die
    
        removescript
    }
    
    //{ game_duplicated
    //
    //    callevent effect_die
    //}
    How should I fix this? Is there a way to make attacks go through entities of the same name/script? Should I make them flee for 1 second if the player is significantly higher enough than the chumtoad? Should I add an ability to throw the player off the chumtoad? Or perhaps a different solution?
     
    Last edited: Nov 3, 2017
  2. Thothie

    Thothie Administrator Staff Member Administrator Moderator Developer

    14,679
    17
    Apr 8, 2005
    psycho-oligist
    lost
    Problem here is that their attacks are hit-scan attacks - so they are blocked by their buddies. You can switch em up for AOE attacks - that may fix it, though it's rougher on the resources. If it turns out to be too rough, or doesn't fix it, you'll have to resort to direct damage attacks. You can do a world only traceline to their target to ensure they at least won't attack through walls.
     
  3. Thothie

    Thothie Administrator Staff Member Administrator Moderator Developer

    14,679
    17
    Apr 8, 2005
    psycho-oligist
    lost
    I assume the idea here is the more often you get bit the stronger the damage gets...

    Might be worth noting this is somewhat similar to how the spider webbing works... In this case, however, there's no visual effect to go with, so it could be done much more efficiently by simply adding a tracker to player/externals (and monster/externals as well, so it has the same effect on summons and other enemy NPCs.) Or... Better yet, use the scriptflag system.

    eg.
    Code:
    { chumbite_damaged_other //assumes dmgevent:chumbite on your chumtoad's xdodamage attack.
        if PARAM1 //I hit
        if $get(PARAM2,relationship,ent_me) equals enemy //didn't hit one of my friends
        local L_CUR_MULTI $get_scriptflag(PARAM2,stackchum,name_value) //find the total value of stackchum
        if ( L_CUR_MULTI < 1 ) local L_CUR_MULTI 1 //in case it's our first bite
        setdmg dmg $math(multiply,DMG_STACK,L_CUR_MULTI) //DMG_STACK being the critter's base damage
        returndata L_CUR_MULTI //welcome to the wonderful world of MSC redundancy
    
        //scriptflags <target> add <name> <type> [value:1] [expiretime:-1] [expiremsg:none]
        scriptflags PARAM2 add stackchum dmgstack 1 10.0 none //add 1 stack that decays in 10 seconds
    }
    And there ya have it all in one.

    Mind, you really need to move this to a dmgevent, otherwise if the mapper chooses to add DOT to these buggers via addparams, those stacks are gonna go up with every DOT tick, as will the DOT damage.

    Also mind with critters that explode you lose a lotta XP. Something for the mapper to keep in mind - they may need to add extra treasure or some easy XP to elsewhere to compensate. Might be kind to give them a set_no_explode as an addparam option.

    edit:
    Also...
    Not... Quite sure what yer trying to do here. I mean HIT_SOUND_RATE is a constant 100, so...

    Okay, first off SOUND_CHANNEL is not 1-100 as you have it defined in the script - you'll probably find that the attack sound often does not play, or sounds odd. The legit sound channels are as follows:
    Code:
        setvarg CHAN_AUTO    0 //first free channel (emanates from entity)
        setvarg CHAN_WEAPON    1 //player HUD channel
        setvarg CHAN_VOICE    2 //entity "voice" channel (emanates from entity)
        setvarg CHAN_ITEM        3 //player back HUD channel (client only)
        setvarg CHAN_BODY    4 //entity "body" channel (emanates from entity)
        setvarg CHAN_WATHER    5 //global weather channel
    Unless it's a looping sound you need to cancel, or one that needs to "follow" the entity around (and in either case it should be a server side sound via svplaysound), or you are playing two overlapping sounds in the same frame, usually you can just stick with 0. Thus:
    Code:
    playsound 0 10 $get_random_token(HIT_SOUNDS)
    It might also be worth noting this is what "playrandomsound" is for. In which case it'd look like this:
    Code:
    const SOUND_ATTACK1 monsters/tube/TubeCritter_Hit1.wav
    const SOUND_ATTACK2 monsters/tube/TuberCritter_Hit2.wav
    const SOUND_ATTACK3 monsters/tube/TubeCritter_Hit3.wav
    [...]
    playrandomsound 0 10 SOUND_ATTACK1 SOUND_ATTACK2 SOUND_ATTACK3
    Though I suppose it probably doesn't save much processing time - token system works fine.

    It would save some processing time to simply check the random generated number rather than calling another event via $func(), since calling events does add a smidgen of overhead (plus script size). So:
    Code:
    if ( $rand(1,100) < SOME_CHANCE )
    Albeit, that's for the others - in this case you're checking against 100, so might as well axe it entirely.

    If you want to get sophisticated, you could scale the pitch and/or volume as the hits become stronger. Both have to be integers, I believe. Volume is 0-10, and pitch 1-400 (with 100 being default - anything over 200 tends to get hypersonic and below 25 unintelligible). Pitch only works with 8-bit sounds though - not sure if those are 8 or 16 bit waves.

    Using the above stack system, you could:
    Code:
    {
    [...]
        const MAX_HIT_VOL 10
        const MAX_HIT_PITCH 200
        const MAX_DMG_STACKS 10
    [...]
    }
    [...]
    { chumbite_damaged_other //assumes dmgevent:chumbite on your chumtoad's xdodamage attack.
        if PARAM1 //I hit
        if $get(PARAM2,relationship,ent_me) equals enemy //didn't hit one of my friends
        local L_CUR_MULTI $get_scriptflag(PARAM2,stackchum,name_value) //find the total value of stackchum
        if ( L_CUR_MULTI < 1 ) local L_CUR_MULTI 1 //in case it's our first bite
        setdmg dmg $math(multiply,DMG_STACK,L_CUR_MULTI) //DMG_STACK being the critter's base damage
        returndata L_CUR_MULTI //welcome to the wonderful world of MSC redundancy
    
        //adjust attack sound by stacks
        local L_VOL_RATIO $int($ratio($math(divide,L_CUR_MULTI,MAX_DMG_STACKS),1,MAX_HIT_VOL))
        local L_PITCH_RATIO $int($ratio($math(divide,L_CUR_MULTI,MAX_DMG_STACKS),50,MAX_HIT_PITCH))
        capvar L_VOL_RATIO 1 10 //probably redundant, just safety
        capvar L_PITCH_RATIO 50 200 //probably redundant, just safety
        playsound 0 L_VOL_RATIO $get_random_token(HIT_SOUNDS) 0.8 L_PITCH_RATIO
    
        if L_CUR_MULTI < MAX_DMG_STACKS //don't add another stack if target at max (as defined by MAX_DMG_STACKS)
        //scriptflags <target> add <name> <type> [value:1] [expiretime:-1] [expiremsg:none]
        scriptflags PARAM2 add stackchum dmgstack 1 10.0 none //add 1 stack that decays in 10 seconds
    }
    Which would cause the volume and (should the wave file allow) pitch to increase as the hits strengthen. (Granted, those strongest hits will probably do as much damage to the player himself as to their character, as they'd likely be being ear shattering squeals.)
     
    Last edited: Nov 3, 2017
  4. greatguys1

    greatguys1 New Adventurer Developer Warriors of the North

    162
    3
    Apr 20, 2013
    Yes
    I'll probably try the direct damage with a world traceline.

    I'm not too into adding stuff like this to the externals- 99% of the time it'll never be used. What would be the advantage to having it there, rather than an effect? I will experiment with the scriptflags though. Ideally, what would you use scriptflags for?

    Yeah- I wanted to make it random when it'd play a noise but it feels better to have the sounds play every time. Haven't got to removing it yet. As for...

    Haven't had any issues yet. But I will change it. I assumed the sound channel was a system in which only a certain amount of sounds could be played at a time from index 0 to x, similar to how old consoles have only so many "voices". I wanted the chumtoad to only be able to emit one sound at a time, overwriting the current sound being played if a new one was played.
    What exactly is a sound channel in this instance?

    Probably would look neater like that. Will change.

    Normally it'd feel neater to have a function, but seeing as how I'm removing all but one of those instances, I'll end up doing this.

    This is a neat idea. Gives indication that something is actually happening with the damage stacking, rather than just larger numbers. The Snark sounds would be perfect for this.

    Thanks for looking it over, I really appreciate the feedback.
    Also thanks for letting me see the forum again

    Missed a few things:
    Will do

    Will make that as a param, probably just for straight explode chance.
     
    Last edited: Nov 3, 2017
  5. Thothie

    Thothie Administrator Staff Member Administrator Moderator Developer

    14,679
    17
    Apr 8, 2005
    psycho-oligist
    lost
    Applyeffects add a lot of overhead, particularly if they get applied often. You're loading up a new script in real time and all the work that goes with sticking it onto the entity. It creates a temporary entity to do this, so you're effectively spawning a monster (albeit, a light one).

    I guess you weren't here way back in the day when the heal spell was a stacking applyeffect that healed for about 0.1 per second, per stack, each of which lasted for about 20 seconds. Basically, anyone spamming a heal spell would send the server into paralysis for good long time (was kinda the troll thing to do for awhile).

    It's also among the reasons I wanna move all the DOT effects to an #include of externals using the scriptflags system. The fact that DOT are applyeffects is the primary reason they lag.

    So, yeah, if the scriptflags are too complex, adding an external counter and pulling the resulting scriptvar requires all of six lines or so in the externals.

    Reminds me, I also need to make a shared externals, as there's a lot of externals like that which apply to both player and monsters.

    (Also, sorry about the whole fuxing the forums for ya thing - WotN's subforum is being a pain - still learning the new forum ops.)

    Each entity in Half-life has five (actually six) reserved sound channels you can designate, as described in that post, and then yeah, another 55 dynamic ones it allocates automatically. Ya use 0 for automatic, and then one of those other channels when you need to be able to alter the sound later, or, in MSC's case, have it follow an entity around, and the like.

    With svplaysound you can put an autoloop sound on an entity, and then change its pitch, volume, and/or attenuation later by playing the same sound on the same channel. You cancel the loop by playing that same sound on the same channel at 0 volume. If you have two different sounds you want to start at the same time in the same event, ya also need to set channels for them (though that can be done with regular old playsound, and doesn't need to be server-side). Server-side sounds played on channels 1, 2, or 4 will follow the entity around. ...and I *think* playing the same sound on the same channel with "svsound.play3d" will cause it to relocate, rather than make a new instance of the same sound (no promises, can't recall if I tested that). The disadvantage to server-side sounds is that they need to be precached - or game go smoosh - and this adds to critical overhead. Check your log_msdll.log for sounds that are already precached universally (all the sounds listed before "World Spawn END"). Ya can re-use any of those without adding overhead (same with models/sprites).
     
  6. greatguys1

    greatguys1 New Adventurer Developer Warriors of the North

    162
    3
    Apr 20, 2013
    Yes
    Kinda as a compromise between an external and removing the applyeffect, I'm trying to add the damage stack system as something you can include on a monster. Ran into some issues. I managed to get around them, but its very hack-ish. I would like your opinion on how the problems were "solved" though.
    Scriptflags aren't stacking, even with the required name, and I even tried prefixing the type with "stack" as well. It didn't overwrite the expired time though. I worked around this by having an "add" when the scriptflag doesn't exist, and an "edit" when it does exist, overwriting the info that's there.

    xdodamage only lets me do <prefix>_dodamage, which returndata can't effect.
    To get around it, I saved the setdmg and returndata to vards, and set a vard as a flag to tell game_damaged_other when it's ok to do returndata.

    Here's what the include looks like:
    Code:
    //Increasing damage from the same monster via a multiplier. Originally built for the chumtoad. By greatguys1
    //Huge contributions from Thothie, thanks
    
    //Damage that you want to stack must have the flag: dmgevent:dmgstk
    //Otherwise, this will default to game_damaged, which will stack dots potentially added from addparams from the mapper.
    
    //Accepts params:
    //const STACK_FLAG_NAME "stackdmg_generic" //What name will be stored under the scriptflag
    //const STACK_MULT_ADD 0.1 //Increment factor for multiplier
    //const STACK_MULT_MAX 10 //Max multiplier incrementing can achieve
    //const STACK_EXPIRE 5 //How long till the scriptflag expires
    
    #scope server
    
    {
        const STACK_FLAG_NAME "stackdmg_generic"
        const STACK_MULT_ADD 0.1
        const STACK_MULT_MAX 10
        const STACK_EXPIRE 5
    
        const STACK_ID "stackdmg"
    
        setvard CALLING_DMGSTK 0
        setvard STACK_ADJUST_DMG 0
    
        setvard STACK_SETDMG 0
        setvard STACK_RETURNDATA 0
    }
    
    { dmgstk_dodamage //PARAM1=hit:0|1 PARAM2=ent_hit PARAM3=(start) PARAM4=(end) PARAM5=DmgType PARAM6=DmgAmt
    
        setvard CALLING_DMGSTK 1
        dbg "Using dmgstk_dodamage for stack."
    
        if ( PARAM1 )
        {
            local L_TARGET PARAM2
    
            if ( $get(L_TARGET,relationship,ent_me) equals enemy ) //didn't hit one of my friends
            {
                local L_PARAM_PASS PARAM6
                callevent do_stack L_TARGET L_PASS_PARAM
            }
        }
    }
    
    { game_dodamage //PARAM1=hit:0|1 PARAM2=ent_hit PARAM3=(start) PARAM4=(end) PARAM5=DmgType PARAM6=DmgAmt
    
        if ( !CALLING_DMGSTK )
        {
            dbg "Using game_dodamage for stack; potentially unwanted; potential problems."
    
            if ( PARAM1 )
            {
                local L_TARGET PARAM2
    
                if ( $get(L_TARGET,relationship,ent_me) equals enemy ) //didn't hit one of my friends
                {
                    local L_PASS_PARAM PARAM6
                    callevent do_stack L_TARGET L_PASS_PARAM
                }
            }
        }
    }
    
    { game_damaged_other //PARAM1=target_hit PARAM2=dmg PARAM3=dmg_type
    
        if ( STACK_ADJUST_DMG )
        {
            setdmg PARAM3 STACK_SETDMG
            returndata STACK_RETURNDATA
    
            setvard STACK_ADJUST_DMG 0
        }
    }
    
    { do_stack //PARAM1 = Target PARAM2 = dmgamt
    
        local L_TARGET PARAM1
        local L_DMG PARAM2
    
        setvard STACK_ADJUST_DMG 1
    
        if ( !$get_scriptflag(L_TARGET,STACK_FLAG_NAME,name_exists) )
        {
            scriptflags L_TARGET add STACK_FLAG_NAME STACK_ID 1 STACK_EXPIRE none
        }
    
        local L_CUR_MULT $get_scriptflag(L_TARGET,STACK_FLAG_NAME,name_value) //find the total value of STACK_FLAG_NAME
    
        capvar L_CUR_MULT 1 STACK_MULT_MAX //Clamp
      
        setvard STACK_SETDMG $math(multiply,L_DMG,L_CUR_MULT)
        setvard STACK_RETURNDATA L_CUR_MULT
    
        add L_CUR_MULT STACK_MULT_ADD
        scriptflags L_TARGET edit STACK_FLAG_NAME STACK_ID L_CUR_MULT STACK_EXPIRE none //add stack that decays
        //scriptflags <target> add <name> <type> [value:1] [expiretime:-1] [expiremsg:none]
    }
    
    Theoretically, if you set up the consts right, you can have multiple enemies with the stacking damage ability, but with their own multiplier to stack up on. Probably not a good idea to have more than one type of enemy like that attacking you, but it's there.
     
  7. Thothie

    Thothie Administrator Staff Member Administrator Moderator Developer

    14,679
    17
    Apr 8, 2005
    psycho-oligist
    lost
    Bugger and double bugger...

    I'll have to set up some tests, but the code is indeed set up so that scriptflags should stack that way... I suppose your workaround is okay... More importantly dmgevent_damaged_other should work that way as well - although looking at the code maybe it's only doing so for registered weapon attacks, which would need to be fixed. Problem comes in where you have, for instance, a critter with this #include and an AOE attack.

    You *could* work this in as an applyeffect so a mapper could add it to any monster dynamically. It wouldn't be as bad as the previous setup, as it wouldn't be trying to add the applyeffect with each attack - rather it'd just tack the script on once when the monster was spawned. Granted, there's still the problem that there is no universal way that I can think of to recognize and separate the critter's primary attack from any DOT it may tack on. Would be nice if our mobs were better organized in that fashion, among others, but meh, reworking several thousand monster scripts to uniform them is not gonna be fun.

    It *might* be something we can help fix from the DOT end, however, and there's only so many of those. The damage type filter only checks if the string contains "fire", "cold", "lightning", or whatnot, so you can tack on suffixes to that all ya want. Might help us with this sorta problem if all the DOT scripts tacked _dot to the damage type to identify it as such. As it is, they already all add on _effect, so DOT effects don't end up being parried. (This is among the reasons I pointed out to the MSS team that they really need a more sophisticated damage struct, so they don't end up in our boat - too late for us to go back and turn it into a mslist or some such.)

    (Also need to fix that skip() problem before we do a release.)
     
  8. greatguys1

    greatguys1 New Adventurer Developer Warriors of the North

    162
    3
    Apr 20, 2013
    Yes
    Before I do that I'm gonna ask, which would you prefer?

    What skip problem?

    Edit:
    Can't do changing pitch in sound if I'm using playrandomsound... changing sounds back into tokens.
     
    Last edited: Nov 5, 2017
  9. Thothie

    Thothie Administrator Staff Member Administrator Moderator Developer

    14,679
    17
    Apr 8, 2005
    psycho-oligist
    lost
    Ya mentioned it in the skip() bug report forums... I need to add it to code requests, along with the dmgevent and scriptflags stack bugs (though I could probably handle those).

    ...and yeah, I did mean to mention if you want to change pitch you can't use playrandomsound. Again, your token string method is probably is about the same overhead. Also, again, 8-bit waves only. You can check the bits the sound uses with Goldwave, I suppose, though MPC will tell you under Properties.

    As for which I'd prefer... I don't see this being a wildly popular monster modification - it'd be a bit unintuitive if it were - rather it'll probably be unique to particular swarm critters, plus it probably wouldn't work right with a lotta critters due to AOE and DOTs. I could see where a variant of it would be good for Scarabs though. In their case, they are already rigged up to increase damage with the more that are latched on (monsters/scarab_fire) - they use a simpler external call (ext_scarab_latch) combined with an applyeffect... Which they probably shouldn't, but they predate the functions that could be used to avoid it.

    Should point out that the Scarabs lack AI specifically because they are designed to spawn in large swarms. It's good that you have a low-poly model, but if you intend to have a lot of these running about, something to consider - custom AI is a pain in the butt though. monsters/base_stripped_ai includes externals, but they are bad at navigation and the like.
     
  10. greatguys1

    greatguys1 New Adventurer Developer Warriors of the North

    162
    3
    Apr 20, 2013
    Yes
    oyeah
    I've managed to forget about that...

    About 5-6 of them are sufficient to kill a 900+ hp character efficiently, though I was thinking of nerfing it so it'd take ~10. I'm thinking that'd be fine as long as its not combined with too many other enemies?

    Edit:
    I've just realized that the scriptflag doesn't clear on the player's death. I don't know how to go about fixing that without doing something with the externals.
     
    Last edited: Nov 6, 2017
  11. Thothie

    Thothie Administrator Staff Member Administrator Moderator Developer

    14,679
    17
    Apr 8, 2005
    psycho-oligist
    lost
    Towards the bottom of player/player_main->{ game_death you will see a list of scriptflags that are cleared. Sadly, you would have to add to that. Though, maybe not a big deal if the scriptflag is set to expire in 5-10 seconds anyways.

    I should make a list of scriptflag names and types in use, similar to the list of quest tags at the top of that script.
     
  12. greatguys1

    greatguys1 New Adventurer Developer Warriors of the North

    162
    3
    Apr 20, 2013
    Yes
    I think the Chumtoad is done. Could you look it over to see if it's ok? I'll also be providing the gibs cleffect I created.
    Chumtoad:
    Code:
    //Chumtoad by greatguys1
    //This doens't follow the original concept of it from hl1 what-so-ever.
    //The idea is to have it like "zerg" where they're most effective in numbers, having damage scale higher the more it attacks, and even more when more are attacking the same target.
    
    #scope server
    
    {
        //Settings for base monster new
        setvar ANIM_RUN "hop_1"
        setvar ANIM_WALK "hop_1"
        setvar ANIM_IDLE "idle"
        setvard ANIM_ATTACK "flinch2"
    
        setvard NPC_NO_ATTACK 0
      
        setvard ATTACK_MOVERANGE 10
        setvard ATTACK_RANGE 50
        setvard ATTACK_HITRANGE 70
        const ATTACK_HITCHANCE 80
    
        const FLEE_HEALTH 0
        const FLEE_CHANCE 0
    
        setvard CANT_FLEE 1
        setvard CAN_RETALIATE 1
        setvard CAN_FLINCH 0
    
        //Monster explode
        const EXPLOSION_DAMAGE 65
    
        //Other stuff particular to this script
        const ANIM_CHARGE "idle2"
        const ANIM_SUICIDE "flinch1"
        setvard ANIM_IDLE3_CHANCE 5 //% chance to use the idle3 animation, slower but more damage
        const LONG_ATTACK 35 //Not long range, but taking longer to strike.
        const SHORT_ATTACK 15
    
        const MONSTER_HEALTH $get(ent_me,maxhp) //I think this'll grab it again should it change.
    
        const GIB_BURSTER_SCRIPT "effects/sfx_gib_burst_alien"
        const GIB_BURSTER_FORCE 300
    
        const EXPLOSION_SFX "effects/sfx_sprite"
        const EXPLOSION_SPRITE "oculus/exp_green.spr"
        const EXPLOSION_SFX_SOUND "monsters/tube/Tube_ExplodingDeath.wav"
    
        const IDLE_SOUND1 "monsters/ogre_welp/bc_idle2.wav"
        const IDLE_SOUND2 "monsters/ogre_welp/bc_idle3.wav"
        const IDLE_SOUND3 "monsters/ogre_welp/bc_idle4.wav"
    
        const DEATH_SOUND1 "monsters/bat/pain1.wav"
        const DEATH_SOUND2 "monsters/bat/pain2.wav"
        const DEATH_SOUND3 "monsters/beetle/idle.wav2"
        const DEATH_SOUND4 "monsters/beetle/idle3.wav"
    
        const PAIN_SOUND1 "monsters/ogre_welp/bc_pain1.wav"
        const PAIN_SOUND2 "monsters/ogre_welp/bc_pain2.wav"
        const PAIN_SOUND3 "monsters/ogre_welp/bc_pain3.wav"
    
        const HIT_SOUNDS "monsters/tube/TubeCritter_Hit1.wav;monsters/tube/TuberCritter_Hit2.wav;monsters/tube/TubeCritter_Hit3.wav"
    
        const PITCH_MIN 30
        const PITCH_MAX 200
    
        setvard SUICIDE_CHANCE 0 //% chance
        const SUICIDE_THRESHOLD 0.7 //Multiplier of what health I need to be under before I check against chance to explode
        const SUICIDE_DISTANCE 100 //Distance affected by explosion
        setvard SUICIDING 0
        setvard TRIED_SUICIDE 0
    
        const BLINK_FREQ 5
        const BLINK_DUR 0.2 //For each step
        setvard BLINK_STEP 0
        const BLINK_MAX 2 //Two other than the idle, eye open state.
        setvard BLINK_CYCLE 1 //1 for up, -1 for down
    
        setvard HACKING_ATK_DIST 0
    
        setvard DO_IDLE_NOISES 1
        const IDLE_NOISE_FREQ 5
    }
    
    #include monsters/base_monster_new
    #include test_scripts/monster_explode
    #include test_scripts/damage_stack
    
    { game_precache
    
        precache monsters/chumtoad.mdl
        precache EXPLOSION_SPRITE
        precache agibs.mdl
    }
    
    { npc_spawn
    
        name "a|Chumtoad"
        race vermin
        hp 300
        setmodel "monsters/chumtoad.mdl"
        width 20
        height 40
        setmoveanim ANIM_RUN
        setidleanim ANIM_IDLE
        blood green
        roam 0
    
        playanim once ANIM_IDLE
        setvard SOUND_CHANNEL CHAN_VOICE
    
        callevent BLINK_FREQ do_blinking
        callevent IDLE_NOISE_FREQ play_idle
    }
    
    { play_idle
    
        if ( DO_IDLE_NOISES )
        {
            playrandomsound SOUND_CHANNEL 10 IDLE_SOUND1 IDLE_SOUND2 IDLE_SOUND3
        }
    
        callevent IDLE_NOISE_FREQ play_idle
    }
    
    { do_blinking
    
        local L_PROPS $get(ent_me,renderprops)
        local L_SKIN $get_token(L_PROPS,4)
    
        setvard BLINK_STEP $math(add,BLINK_STEP,BLINK_CYCLE)
    
        if ( BLINK_STEP >= BLINK_MAX )
        {
            setvard BLINK_CYCLE -1
        }
        else if ( BLINK_STEP <= 0 )
        {
            setvard BLINK_CYCLE 1
        }
    
        if ( L_SKIN < 3 ) //In case a mapper changes the skin
        {
            setprop ent_me skin BLINK_STEP
        }
    
        if ( BLINK_STEP == 0 )
        {
            callevent BLINK_FREQ do_blinking
        }
        else
        {
            callevent BLINK_DUR do_blinking
        }
    }
    
    { game_damaged
    
        local L_HP $get(ent_me,hp)
    
        if ( L_HP <= $math(multiply,MONSTER_HEALTH,SUICIDE_THRESHOLD) )
        {
            if ( !TRIED_SUICIDE )
            {
                setvard TRIED_SUICIDE 1
    
                if ( $rand(1,100) <= SUICIDE_CHANCE )
                {
                    callevent do_suicide_charge
                }
            }
        }
    
        playrandomsound SOUND_CHANNEL 10 PAIN_SOUND1 PAIN_SOUND2 PAIN_SOUND3
    }
    
    { dmgstk_dodamage //PARAM1=hit:0|1 PARAM2=ent_hit PARAM3=(start) PARAM4=(end) PARAM5=DmgType PARAM6=DmgAmt
    //Thanks Thothie for most of this event
    
        if ( PARAM1 ) //I hit
        {
            local L_TARGET PARAM2
    
            setvard HACKING_ATK_DIST 1
    
            local L_MULT $get_scriptflag(L_TARGET,STACK_FLAG_NAME,name_value)
            subtract L_MULT 0.1 //Upon the first attack, the get scriptflag will always return 1.1, 'cuz the system added it already. I did a 1.0 attack though. Compensating here.
            local L_PITCH $ratio($math(divide,L_MULT,STACK_MULT_MAX),PITCH_MIN,PITCH_MAX) //The math gets a number between 0-1 depending on how much it stacked already.
    
            playsound SOUND_CHANNEL 10 $get_random_token(HIT_SOUNDS) 0.8 L_PITCH
        }
    }
    
    { game_damaged_other //PARAM1=target_hit PARAM2=dmg PARAM3=dmg_type
    
        if ( HACKING_ATK_DIST ) //Unfortunately, I don't think this will have effect on the damage stacker without adding another flag. I already have too many. If it missed here, it likely added a stack. Hopefully shouldn't be too detrimental
        {
            local L_HACK_START $get(ent_me,origin)
            local L_HACK_END $get(PARAM1,origin)
    
            local L_HACK_HITRANGE ATTACK_HITRANGE //Unfortunately need to hack hitrange because of varying enemies width.
            add L_HACK_HITRANGE $math(divide,$get(PARAM1,width),2)
    
            if ( $get(PARAM1,isplayer) ) //Hack in extra distance with a player because their origin is in the middle of the ent while others are at their feet.
            {
                add L_HACK_HITRANGE $math(divide,$get(PARAM1,height),2)
            }
    
            if ( $dist(L_HACK_START,L_HACK_END) >= L_HACK_HITRANGE )
            {
                returndata 0
            }
            else if ( $get_traceline(L_HACK_START,L_HACK_END,worldonly) )
            {
                returndata 0
            }
    
            setvard HACKING_ATK_DIST 0
        }
    }
    
    { game_death
    
        playrandomsound SOUND_CHANNEL 10 DEATH_SOUND1 DEATH_SOUND2 DEATH_SOUND3 DEATH_SOUND4
    }
    
    { do_suicide_charge
    
        callevent npcatk_suspend_ai
        playanim critical ANIM_CHARGE
        setvard SUICIDING 1
    }
    
    { finish_charge //Called from the model
    
        playanim critical ANIM_SUICIDE
    }
    
    { finish_suicide //Called from the model
    
        setprop ent_me rendermode 5
        setprop ent_me renderamt 0
    
        callevent do_explode
        callevent npc_suicide
    }
    
    { do_explode
    
        local L_VEC $get(ent_me,origin)
        vectoradd L_VEC $vec(0,0,30)
    
        local L_COL $clcol(0,0,0)
        local L_STR "0;3;255;add;"
        stradd L_STR L_COL
        stradd L_STR ";20;10"
    
        clientevent new all EXPLOSION_SFX L_VEC EXPLOSION_SPRITE L_STR 0.5
        clientevent new all GIB_BURSTER_SCRIPT L_VEC GIB_BURSTER_FORCE
        playsound 0 10 EXPLOSION_SFX_SOUND
    }
    
    { beam_dodamage //PARAM1=hit:0|1 PARAM2=ent_hit PARAM3=(start) PARAM4=(end) PARAM5=DmgType PARAM6=DmgAmt
    
        if ( PARAM1 ) //Hack for explosion to do stack damage. Really getting tired of ""hacking"" all this. This script is gonna turn out a mess.
        {
            local L_TARGET PARAM2
    
            if ( $get(L_TARGET,relationship,ent_me) equals enemy )
            {
                local L_PASS_PARAM PARAM6
                callevent do_stack L_TARGET L_PASS_PARAM
            }
        }
    }
    
    { npc_selectattack
    
        if ( $rand(0,100) <= ANIM_IDLE3_CHANCE )
        {
            setvard ANIM_ATTACK idle3
        }
        else
        {
            setvard ANIM_ATTACK flinch2
        }
    }
    
    { attack_1 //Called from the model
    
        callevent do_attack LONG_ATTACK
    }
    
    { attack_2 //Called from the model
    
        callevent do_attack SHORT_ATTACK
    }
    
    { do_attack //PARAM1 = damage
    
        xdodamage NPCATK_TARGET direct PARAM1 ATTACK_HITCHANCE ent_me ent_me none pierce dmgevent:dmgstk
        //Doing direct damage so chumtoads can hit through each other.
    }
    
    { cycle_up
    
        setvard DO_IDLE_NOISES 0
    }
    
    { cycle_down
    
        setvard DO_IDLE_NOISES 1
    }
    
    { ext_suicide_chance //PARAM1 = new suicide chance //Intended to be called via the map.
    
        setvard SUICIDE_CHANCE PARAM1
    }
    monster_explode:
    Code:
    //Suicide Explosion base by greatguys1
    
    //Call do_explode from the top script to have the monster explode.
    //Initiate any cleffects from a do_explode in the top script.
    
    //Cutomizable vars
    // const EXPLOSION_DISTANCE [num] default: 120 "The radius of the explosion"
    // const EXPLOSION_DAMAGE [num] default: 300 "How much damage will the explosion do"
    // const EXPLOSION_DAMAGE_FALLOFF [0-1] default: 0.2 "How much less damage will do from the center; 1 will do no damage at the very edge of the radius."
    // const EXPLOSION_FORCE [num] default: 300 "How much force people caught in the radius will be pushed"
    // const EXPLOSION_TYPE [damage type] default: blunt_effect "Which element to use when damaging enemies"
    
    #scope server
    
    {
        const EXPLOSION_DISTANCE 120
        const EXPLOSION_DAMAGE 300
        const EXPLOSION_DAMAGE_FALLOFF 0.2
        const EXPLOSION_FORCE 300
        const EXPLOSION_TYPE blunt_effect
    }
    
    { do_explode
    
        if ( EXPLOSION_DAMAGE )
        {
            xdodamage $get(ent_me,origin) EXPLOSION_DISTANCE EXPLOSION_DAMAGE EXPLOSION_DAMAGE_FALLOFF ent_me ent_me none EXPLOSION_TYPE dmgevent:beam //<target|(src_origin)> <range|aoe|(dest_origin)|direct> <damage> <cth|fall_off> <attacker> <inflciter> <skill|none> <dmg_type> [flag_string]
        }
    }
    
    { beam_dodamage //PARAM1=hit:0|1 PARAM2=ent_hit PARAM3=(start) PARAM4=(end) PARAM5=DmgType PARAM6=DmgAmt //Thanks Thothie!
    
        if ( PARAM1 )
        {
            local L_TARGET PARAM2
    
            if ( $get(L_TARGET,relationship,ent_me) equals enemy )
            {
                if ( EXPLOSION_FORCE != 0 )
                {
                    local L_YAW $angles($get(ent_me,origin),$get(L_TARGET,origin))
                    addvelocity L_TARGET $relvel($vec(0,L_YAW,0),$vec(0,EXPLOSION_FORCE,$math(divide,EXPLOSION_FORCE,1.3)))
                }
            }
        }
    }
    damage_stack:
    Code:
    //Increasing damage from the same monster via a multiplier. Originally built for the chumtoad. By greatguys1
    //Huge contributions from Thothie, thanks
    
    //Damage that you want to stack must have the flag: dmgevent:dmgstk
    //Otherwise, this will default to game_damaged, which will stack dots potentially added from addparams from the mapper.
    
    //Accepts params:
    //const STACK_FLAG_NAME "stackdmg_generic" //What name will be stored under the scriptflag
    //const STACK_MULT_ADD 0.1 //Increment factor for multiplier
    //const STACK_MULT_MAX 10 //Max multiplier incrementing can achieve
    //const STACK_EXPIRE 5 //How long till the scriptflag expires
    
    #scope server
    
    {
        const STACK_FLAG_NAME "stackdmg_generic"
        const STACK_MULT_ADD 0.1
        const STACK_MULT_MAX 10
        const STACK_EXPIRE 5
    
        const STACK_ID "stackdmg"
    
        setvard CALLING_DMGSTK 0
        setvard STACK_ADJUST_DMG 0
    
        setvard STACK_SETDMG 0
        setvard STACK_RETURNDATA 0
    }
    
    { dmgstk_dodamage //PARAM1=hit:0|1 PARAM2=ent_hit PARAM3=(start) PARAM4=(end) PARAM5=DmgType PARAM6=DmgAmt
    
        setvard CALLING_DMGSTK 1
        dbg "Using dmgstk_dodamage for stack."
    
        if ( PARAM1 )
        {
            local L_TARGET PARAM2
    
            if ( $get(L_TARGET,relationship,ent_me) equals enemy ) //didn't hit one of my friends
            {
                local L_PASS_PARAM PARAM6
                callevent do_stack L_TARGET L_PASS_PARAM
            }
        }
    }
    
    { game_dodamage //PARAM1=hit:0|1 PARAM2=ent_hit PARAM3=(start) PARAM4=(end) PARAM5=DmgType PARAM6=DmgAmt
    
        if ( !CALLING_DMGSTK )
        {
            dbg "Using game_dodamage for stack; potentially unwanted; potential problems."
    
            if ( PARAM1 )
            {
                local L_TARGET PARAM2
    
                if ( $get(L_TARGET,relationship,ent_me) equals enemy ) //didn't hit one of my friends
                {
                    local L_PASS_PARAM PARAM6
                    callevent do_stack L_TARGET L_PASS_PARAM
                }
            }
        }
    }
    
    { game_damaged_other //PARAM1=target_hit PARAM2=dmg PARAM3=dmg_type
    
        if ( STACK_ADJUST_DMG > 0 )
        {
            setdmg PARAM3 STACK_SETDMG
            returndata STACK_RETURNDATA
    
            subtract STACK_ADJUST_DMG 1
        }
    }
    
    { do_stack //PARAM1 = Target PARAM2 = dmgamt
    
        local L_TARGET PARAM1
        local L_DMG PARAM2
    
        add STACK_ADJUST_DMG 1 //Hopefully will take care of the case of AoE attacks.
    
        if ( !$get_scriptflag(L_TARGET,STACK_FLAG_NAME,name_exists) )
        {
            scriptflags L_TARGET add STACK_FLAG_NAME STACK_ID 1 STACK_EXPIRE none
        }
    
        local L_CUR_MULT $get_scriptflag(L_TARGET,STACK_FLAG_NAME,name_value) //find the total value of STACK_FLAG_NAME
    
        capvar L_CUR_MULT 1 STACK_MULT_MAX //Clamp
      
        setvard STACK_SETDMG $math(multiply,L_DMG,L_CUR_MULT)
        setvard STACK_RETURNDATA L_CUR_MULT
    
        add L_CUR_MULT STACK_MULT_ADD
        scriptflags L_TARGET edit STACK_FLAG_NAME STACK_ID L_CUR_MULT STACK_EXPIRE none //add stack that decays
        //scriptflags <target> add <name> <type> [value:1] [expiretime:-1] [expiremsg:none]
    }
    sfx_gib_base_burst:
    Code:
    //Gib burst by greatguys1
    //This is meant to be #included into cleffects that make use of the options provided. There are no defaults where media is required.
    //Takes inspiration from sfx_explode.
    
    #scope client
    
    {
        const GIB_MODEL none //[model name] Which gib model to use
        const GIB_FORCE_SUBMODEL none //[idx] Force a submodel; don't override if you wish to use random submodels
        const GIB_SUBMODELS none //[num] How many submodels does it have? Not needed if forcing a submodel
    
        const GIB_AMT 5 //[num] How many gibs do you want
    
        const GIB_TIME 6 //[num] How long do gibs stay alive
        const GIB_BOUNCE_FACTOR 1.3 //[0-1] A float of the bounce multiplier.
        const GIB_GRAV 0.7 //[num] Multiplier for gravity, 1 is normal.
        const GIB_SCALE 1 //[num] Multiplier for scale. 1 is normal size
        const GIB_COLLISION "world" //["world"|"all"|"none"] What to collide with.
        const GIB_DIE_ON_COLLIDE 0 //[0|1] Die on collision? Must also be used with "world" or "all".
        const GIB_RENDER_MODE "normal" //["normal"|"color"|"texture"|"glow"|"alpha"|"add"] Too long to list, refer to scripting_all_docs under cleffect
        const GIB_RENDER_FX "normal" //["normal"|"glow"|"player"] --------------------------^
        const GIB_RENDER_AMT 0 //Amount of effect applied by rendermode and/or renderfx
        const GIB_COLOR 0 //(r,g,b) color
        const GIB_FADEOUT "lifetime" //How long to take till it fades out, usually should be equal to its lifetime.
        const GIB_SPIN_MULT 1 //[num] Multiplier for how fast the gibs spin while in the air.
    
        const GIB_SPIN_MAX 5
        const MAX_ANG 359
    }
    
    { client_activate //<origin> <force>
    
        setvard FX_CENTER PARAM1
        setvard FX_FORCE PARAM2
    
        calleventloop GIB_AMT create_gibs
    
        callevent 3.0 remove_me
    }
    
    { create_gibs
    
        cleffect tempent model GIB_MODEL FX_CENTER setup_gib update_gib
    }
    
    { update_gib
      
    }
    
    { setup_gib
    
        local L_PITCH $rand(0,MAX_ANG)
        local L_YAW $rand(0,MAX_ANG)
        local L_ROLL $rand(0,MAX_ANG)
    
        local L_ANG $vec(L_PITCH,L_YAW,L_ROLL)
    
        local L_TOTAL 0
        add L_TOTAL L_PITCH
        add L_TOTAL L_YAW
        add L_TOTAL L_ROLL
    
        local L_VECX $math(multiply,$math(divide,L_PITCH,L_TOTAL),FX_FORCE) //Ratio doesn't wanna fucking work, but this does essentially the same thing.
        local L_VECY $math(multiply,$math(divide,L_YAW,L_TOTAL),FX_FORCE)
        local L_VECZ $math(multiply,$math(divide,L_ROLL,L_TOTAL),FX_FORCE)
    
        local L_VEC2 $vec(L_VECX,L_VECY,L_VECZ)
    
        local L_VEL $relvel(L_ANG,L_VEC2)
      
        cleffect tempent set_current_prop death_delay    GIB_TIME
        cleffect tempent set_current_prop bouncefactor    GIB_BOUNCE_FACTOR
        cleffect tempent set_current_prop gravity    GIB_GRAV
        cleffect tempent set_current_prop scale        GIB_SCALE
        cleffect tempent set_current_prop collide    GIB_COLLISION
    
        if ( GIB_DIE_ON_COLLIDE )
        {
            cleffect tempent set_current_prop collide "die"
        }
    
        cleffect tempent set_current_prop rendermode    GIB_RENDER_MODE                 
        cleffect tempent set_current_prop renderfx    GIB_RENDER_FX             
        cleffect tempent set_current_prop renderamt    GIB_RENDER_AMT
    
        if ( GIB_COLOR )
        {
            cleffect tempent set_current_prop rendercolor GIB_COLOR
        }
    
        cleffect tempent set_current_prop fadeout    GIB_FADEOUT
      
        if ( GIB_FORCE_SUBMODEL )
        {
            cleffect tempent set_current_prop body    GIB_FORCE_SUBMODEL
        }
        else
        {
            cleffect tempent set_current_prop body    $rand(0,$math(subtract,GIB_SUBMODELS,1))
        }
    
        cleffect tempent set_current_prop velocity L_VEL
    
        cleffect tempent set_current_prop angles L_ANG //An unintentional effect of this is that it appears to select a random angle again after hitting the ground. Still works out ok though.
    }
    
    { remove_me
        removescript
    }
    sfx_gib_burst_alien:
    Code:
    //Alien Gib Burst by greatguys1
    
    #scope client
    
    {
        const GIB_MODEL "agibs.mdl" //[model name] Which gib model to use //Turns out it must be included manually in the summmoning script; precachefile doens't work here.
        const GIB_SUBMODELS 4 //[num] How many submodels does it have? Not needed if forcing a submodel
        const GIB_AMT 5
    }
    
    #include effects/sfx_gib_base_burst
    Also add this to your player/player_main on line 486:
    Code:
    scriptflags ent_me cleartype stackdmg
    Or otherwise, all in a nice RAR:
    https://www.dropbox.com/s/vnq3nwe60aisruz/Chumtoad and Scripts.rar?dl=1

    The gibs must be compiled with sc.dll, otherwise they don't work. Chumtoad is currently rigged to have itself, damage_stack, and monster_explode all in the test scripts. If you compile it all into the sc.dll, you'll have to change the includes. Remember to change the player/player_main even if you use the RAR.

    Lots of hacking was done with the attack to ignore entities that are in the way... if stuff gets difficult to understand you can ask here and I'll attempt to explain what I was doing.
     
  13. Thothie

    Thothie Administrator Staff Member Administrator Moderator Developer

    14,679
    17
    Apr 8, 2005
    psycho-oligist
    lost
    Client side scripting isn't working for test_scripts? Bugger...

    There is an effects gibs command, but this is certainly more optimal, as those gibs are all tracked server side. It'd become a problem if there were a lotta explosions.

    I'll try to make sure <dmgevent>_damaged_other and stack type scriptflags work proper next patch, but I dun think those fixes will make it worth re-imagining this.
     
  14. greatguys1

    greatguys1 New Adventurer Developer Warriors of the North

    162
    3
    Apr 20, 2013
    Yes
    It'd certainly help being able to read the script better. I'd redo some stuff here once it's fixed.
     
  15. Thothie

    Thothie Administrator Staff Member Administrator Moderator Developer

    14,679
    17
    Apr 8, 2005
    psycho-oligist
    lost
    Integrating this...

    Renaming/redirecting damage_stack.script and monster_explode.script to monsters/base_damage_stack.script and monsters/base_monster_explode.script respectively.

    Placing sfx_ files in effects/ - which seems to be the intent, but ya provided no folder structure.

    Would test but... Where's the model for this thing again?
     
  16. greatguys1

    greatguys1 New Adventurer Developer Warriors of the North

    162
    3
    Apr 20, 2013
    Yes
    Chumtoad model:
    https://www.dropbox.com/s/lgc4q7crntkwhl0/chumtoad.mdl?dl=1

    Source:
    https://www.dropbox.com/s/23r4qadhhkuc79c/chumtoad source.rar?dl=1

    The source is a decompiled chumtoad with the extra skins and events tied to some frames of animation for attacking and exploding.

    Those are the intended folders. Reminder to change the includes on the chumtoad. I intended to have SUICIDE_CHANCE at 5, but forgot to change it back after testing the addparam.

    Edit: Chumtoad model goes in models/monsters
     
    Last edited: Nov 21, 2017 at 9:00 PM

Share This Page