// Base class for all SWWM Health Class SWWMHealth : Inventory abstract { Mixin SWWMAutoUseFix; Mixin SWWMUseToPickup; Mixin SWWMOverlapPickupSound; Mixin SWWMRespawn; Mixin SWWMRotatingPickup; Mixin SWWMPickupGlow; Mixin SWWMUnrealStyleDrop; // can't use the Health class for whatever reason // nice parser you got there I guess? meta Class giveme; Property GiveHealth : giveme; transient int lastautousetic; // accumulated damage can make the use sounds stack override void AttachToOwner( Actor other ) { Super.AttachToOwner(other); // find last health item that's better than us Inventory found = null; for ( Inventory i=other.Inv; i; i=i.Inv ) { if ( !(i is 'SWWMHealth') || (i == self) || (GetDefaultByType(SWWMHealth(i).giveme).Amount < GetDefaultByType(giveme).Amount) ) continue; found = i; } if ( !found ) { // find first item with health that's worse than us after it for ( Inventory i=other.Inv; i; i=i.Inv ) { if ( (i == self) || !(i.Inv is 'SWWMHealth') ) continue; if ( GetDefaultByType(SWWMHealth(i.Inv).giveme).Amount > GetDefaultByType(giveme).Amount ) continue; found = i; break; } } if ( !found ) { // find last armor item, plating or collar for ( Inventory i=other.Inv; i; i=i.Inv ) { if ( !(i is 'SWWMArmor') ) continue; found = i; } } if ( !found ) { // check if the first item in inventory is a sandwich if ( other.Inv is 'GrilledCheeseSandwich' ) { // we're good return; } // find first item next to a sandwich for ( Inventory i=other.Inv; i; i=i.Inv ) { if ( (i == self) || !(i.Inv is 'GrilledCheeseSandwich') ) continue; found = i; break; } } if ( !found ) return; // place ourselves right after it Inventory saved = found.Inv; found.Inv = self; other.Inv = Inv; Inv = saved; } override bool Use( bool pickup ) { if ( Owner.Health >= GetDefaultByType(giveme).MaxAmount ) return false; // healing items won't get auto-used on pickup if their healing could "be wasted", unless they're powerup health (e.g. Refresher) or bonus health if ( pickup && !bBIGPOWERUP && (default.MaxAmount > 0) && (Owner.Health+GetDefaultByType(giveme).Amount > GetDefaultByType(giveme).MaxAmount) ) return false; if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) { bool bPlayMe = true; if ( self is 'HealthNuggetItem' ) { let hnd = SWWMHandler(EventHandler.Find('SWWMHandler')); if ( hnd ) { if ( hnd.lastnuggettic[Owner.PlayerNumber()] == gametic ) bPlayMe = false; // don't play if picked up on the same exact tic (overlapping items) hnd.lastnuggettic[Owner.PlayerNumber()] = gametic; } } if ( bPlayMe ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA,CHANF_OVERLAP); } SWWMHandler.HealthFlash(Owner.PlayerNumber()); Owner.GiveInventory(giveme,GetDefaultByType(giveme).Amount); if ( Owner.player == players[consoleplayer] ) SWWMScoreObj.SpawnAtActorBunch(GetDefaultByType(giveme).Amount,Owner,Font.CR_BLUE); AutoUseExtra(false); return true; } // additional effects when automatically used // recursive: if true, the auto-use was called on another copy of the // item in a "stacked" heal. can be used to prevent certain // effects from happening multiple times in one go virtual void AutoUseExtra( bool recursive ) { } override void DoEffect() { Super.DoEffect(); if ( Amount <= 0 ) DepleteOrDestroy(); } override void AbsorbDamage( int damage, Name damageType, int &newdamage, Actor inflictor, Actor source, int flags ) { if ( Owner.ApplyDamageFactor(damageType,damage) <= 0 ) return; // this damage type is ignored by the player, so it does not affect us if ( damageType == 'EndLevel' ) return; // don't trigger on endlevel damage if ( (Owner.Health-damage <= (GetDefaultByType(giveme).MaxAmount-GetDefaultByType(giveme).Amount)) ) { newdamage = damage; // lesser healing items can't prevent lethal damage // bigger healing items only autoactivate on lethal damage if ( !bBIGPOWERUP && (Owner.Health-damage <= 0) ) return; else if ( bBIGPOWERUP && (Owner.Health-damage > 0) ) return; if ( (swwm_strictuntouchable == 1) && Owner.player ) { let hnd = SWWMHandler(EventHandler.Find('SWWMHandler')); if ( hnd ) hnd.tookdamage[Owner.PlayerNumber()] = true; } if ( ((Owner.player == players[consoleplayer]) || bBigPowerup) && (lastautousetic < gametic) ) { Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA,CHANF_OVERLAP); lastautousetic = gametic; } int tgive = 0; bool morethanonce = false; while ( (Amount > 0) && (newdamage > 0) ) { newdamage = newdamage-GetDefaultByType(giveme).Amount; if ( Owner.player == players[consoleplayer] ) SWWMScoreObj.SpawnAtActorBunch(GetDefaultByType(giveme).Amount,Owner,Font.CR_BLUE); if ( newdamage < 0 ) Owner.GiveBody(-newdamage,GetDefaultByType(giveme).MaxAmount); newdamage = max(0,newdamage); if ( !morethanonce ) SWWMHandler.HealthFlash(Owner.PlayerNumber()); AutoUseExtra(morethanonce); morethanonce = true; Amount--; } } else newdamage = damage; } Default { +INVENTORY.INVBAR; +INVENTORY.ISHEALTH; +INVENTORY.AUTOACTIVATE; +DONTGIB; Inventory.MaxAmount 5; Inventory.InterHubAmount 5; Inventory.UseSound "misc/health_pkup"; Inventory.PickupFlash 'SWWMBluePickupFlash'; +FLOATBOB; FloatBobStrength 0.25; } }