// common code goes here // extra sound channels for the mod enum ESWWMGZChannels { CHAN_YOUDONEFUCKEDUP = 63200, // exception handler CHAN_DEMOVOICE = 63201, // demolitionist voices CHAN_FOOTSTEP = 63202, // footstep sounds and others CHAN_WEAPONEXTRA = 63203, // additional weapon sounds (usually loops) CHAN_POWERUP = 63204, // powerup sounds CHAN_POWERUPEXTRA = 63205, // additional powerup sounds CHAN_JETPACK = 63206, // jetpack sound CHAN_ITEMEXTRA = 63207, // additional item sounds CHAN_WEAPONEXTRA2 = 63208, // additional weapon sound slot CHAN_WEAPONEXTRA3 = 63209, // additional weapon sound slot (again) CHAN_DAMAGE = 63210, // used for impact/hit sounds CHAN_AMBEXTRA = 63211, // player ambience when submerged CHAN_DEMOVOICEAUX = 63212, // extra channel to make oneliner voices louder CHAN_DEMOVOICEAUX2 = 63213, // how many more channels do I need??? CHAN_DEMOVOICEAUX3 = 63214, // oh god, the loudening CHAN_FUELREGEN = 63215 // sound of fuel regenerating }; const FallbackTag = "AWESOME IT'S PENIS"; // used on tag processing, please don't mind the actual string used) const MaxBouncePerTic = 40; // maximum simultaneous bounces in one tic for a lightweight actor before we consider it's stuck // basic "does nothing" actor, used to remove stuff in CheckReplacement Class SWWMNothing : Actor { States { Spawn: TNT1 A 1; Stop; } } Class SWWMDamageAccumulator : Inventory { Actor inflictor, source; Array amounts; int total; Name type; bool dontgib; int flags; override void DoEffect() { Super.DoEffect(); // so many damn safeguards in this if ( !Owner || (Owner.Health <= 0) ) { Destroy(); return; } int gibhealth = Owner.GetGibHealth(); // お前はもう死んでいる if ( (Owner.health-total <= gibhealth) && !dontgib ) { // safeguard for inflictors that have somehow ceased to exist, which apparently STILL CAN HAPPEN if ( inflictor ) inflictor.bEXTREMEDEATH = true; else type = 'Extreme'; } // make sure accumulation isn't reentrant if ( inflictor && (inflictor is 'EvisceratorChunk') ) inflictor.bAMBUSH = true; // 何? for ( int i=0; i85899345)?int.max:(match.total*25); return match.total; } return 0; } default { +INVENTORY.UNTOSSABLE; +INVENTORY.UNDROPPABLE; +INVENTORY.UNCLEARABLE; } } // Track last damage source to blame fall damage on Class SWWMWhoPushedMe : Inventory { Actor instigator; static void SetInstigator( Actor b, Actor whomst ) { if ( !b || !whomst ) return; SWWMWhoPushedMe ffd = SWWMWhoPushedMe(b.FindInventory("SWWMWhoPushedMe")); if ( ffd ) { ffd.instigator = whomst; return; } ffd = SWWMWhoPushedMe(Spawn("SWWMWhoPushedMe")); ffd.AttachToOwner(b); ffd.instigator = whomst; } static Actor RecallInstigator( Actor b ) { if ( !b ) return null; SWWMWhoPushedMe ffd = SWWMWhoPushedMe(b.FindInventory("SWWMWhoPushedMe")); if ( ffd ) { Actor whomst = ffd.instigator; ffd.Destroy(); return whomst; } return null; } default { +INVENTORY.UNTOSSABLE; +INVENTORY.UNDROPPABLE; +INVENTORY.UNCLEARABLE; } } Class SWWMFlyTracker : Inventory { Actor instigator; Vector3 startpos, curpos; double maxdist; int gracepd; static void Track( Actor b, Actor whomst ) { if ( !b || !whomst ) return; SWWMFlyTracker ffd = SWWMFlyTracker(b.FindInventory("SWWMFlyTracker")); if ( ffd ) { ffd.instigator = whomst; return; } ffd = SWWMFlyTracker(Spawn("SWWMFlyTracker")); ffd.AttachToOwner(b); ffd.instigator = whomst; ffd.curpos = ffd.startpos = b.pos; ffd.maxdist = 0; } override void DoEffect() { maxdist = max(maxdist,level.Vec3Diff(startpos,curpos).length()); if ( !Owner || Owner.bFLOAT || Owner.bNOGRAVITY || (Owner.waterlevel > 1) || (Owner.pos.z <= Owner.floorz) || !Owner.TestMobjZ(false) ) { gracepd++; if ( gracepd < 10 ) return; if ( instigator ) SWWMUtility.AchievementProgress("flight",int(maxdist),instigator.player); Destroy(); return; } gracepd = 0; curpos = Owner.pos; } default { +INVENTORY.UNTOSSABLE; +INVENTORY.UNDROPPABLE; +INVENTORY.UNCLEARABLE; } } // fractic-compatible interpolators, with double value Class SmoothLinearValueInterpolator { private double val, oldval, diff; static SmoothLinearValueInterpolator Create( double val, double diff ) { let v = new("SmoothLinearValueInterpolator"); v.oldval = v.val = val; v.diff = diff; return v; } void Reset( double newval ) { oldval = val = newval; } void Update( double newval ) { oldval = val; if ( abs(newval-val) < diff ) val = newval; else if ( val > newval ) val = max(newval,val-diff); else val = min(newval,val+diff); } double GetValue( double fractic = 1. ) { return (val~==oldval)?val:SWWMUtility.Lerp(oldval,val,fractic); } } Class SmoothDynamicValueInterpolator { private double val, oldval, factor, mindiff, maxdiff; static SmoothDynamicValueInterpolator Create( double val, double factor, double mindiff, double maxdiff ) { let v = new("SmoothDynamicValueInterpolator"); v.oldval = v.val = val; v.factor = factor; v.mindiff = mindiff; v.maxdiff = maxdiff; return v; } void Reset( double newval ) { oldval = val = newval; } void Update( double newval ) { oldval = val; if ( abs(newval-val) < mindiff ) val = newval; else { double diff = min(abs(newval-val)*factor,maxdiff); if ( val > newval ) val = max(newval,val-diff); else val = min(newval,val+diff); } } double GetValue( double fractic = 1. ) { return (val~==oldval)?val:SWWMUtility.Lerp(oldval,val,fractic); } }