// gesture effects Class LoveHeartTrail : Actor { Default { RenderStyle "Add"; Radius .1; Height 0.; Alpha .1; +NOGRAVITY; +NOBLOCKMAP; +NOINTERACTION; +DONTSPLASH; +NOTELEPORT; +FORCEXYBILLBOARD; } override void Tick() { if ( isFrozen() ) return; A_FadeOut(.01); scale *= .95; } States { Spawn: DOKI A -1 Bright; Stop; } } Class LoveHeartSparkle : Actor { Default { Radius .1; Height 0.; Scale .03; +NOGRAVITY; +NOBLOCKMAP; +NOINTERACTION; +DONTSPLASH; +NOTELEPORT; +FORCEXYBILLBOARD; } override void PostBeginPlay() { Scale *= FRandom[ExploS](.75,1.5); specialf1 = FRandom[ExploS](.95,.98); specialf2 = FRandom[ExploS](.01,.03); vel = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),sin(-pitch))*FRandom[ExploS](2,8); } override void Tick() { if ( isFrozen() ) return; A_SetScale(scale.x*specialf1); A_FadeOut(specialf2); Vector3 dir = vel; double magvel = dir.length(); magvel *= .99; if ( magvel > 0. ) { dir /= magvel; dir += .2*(FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)); vel = dir.unit()*magvel; } SetOrigin(level.Vec3Offset(pos,vel),true); } States { Spawn: DOKI A -1 Bright; Stop; } } Class LoveHeartBurstLight : PaletteLight { Default { Tag "LovePal"; ReactionTime 15; Args 0,0,0,150; } } Class LoveHeart : Actor { Default { Obituary "$O_DOKIDOKI"; DamageType 'Love'; DamageFunction (clamp(special2,5,15)); Radius 4; Height 4; Speed 10; Scale .2; PROJECTILE; +BLOODLESSIMPACT; +FORCEXYBILLBOARD; +SEEKERMISSILE; +FOILINVUL; +PAINLESS; +NODAMAGETHRUST; } override int DoSpecialDamage( Actor target, int damage, Name damagetype ) { bEXTREMEDEATH = false; bNOEXTREMEDEATH = false; SWWMStats s = null; if ( Demolitionist(self.target) ) s = Demolitionist(self.target).mystats; if ( s ) s.smooch++; let raging = RagekitPower(self.target.FindInventory("RagekitPower")); if ( (target is 'WolfensteinSS') || (target.Species == 'WolfensteinSS') ) target.bFRIENDLY = false; if ( target.IsFriend(self.target) || SWWMUtility.IdentifyingDog(target) ) { int healamt = clamp(special2,5,15); if ( raging ) { healamt *= 8; raging.DoHitFX(); } if ( target.GiveBody(healamt,target.GetSpawnHealth()) ) { SWWMScoreObj.Spawn(healamt,target.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+target.Height/2),ST_Health); SWWMHandler.DoFlash(target,Color(32,224,128,255),10); } if ( SWWMUtility.IdentifyingDog(target) ) { // befriend good doggo if ( target.bCOUNTKILL ) { target.bCOUNTKILL = false; level.total_monsters--; } if ( !target.bFRIENDLY && s ) s.befriend++; target.bFRIENDLY = true; if ( deathmatch ) target.SetFriendPlayer(self.target.player); } return 0; } Vector3 dirto = level.Vec3Diff(pos,target.Vec3Offset(0,0,target.Height/2)).unit(); SWWMUtility.DoKnockback(target,dirto,1500.*damage); let bread = target.FindState("Pain"); if ( bread ) target.SetState(bread); if ( raging ) { damage *= 8; raging.DoHitFX(); } if ( (target is 'WolfensteinSS') || (target.Species == 'WolfensteinSS') ) { damage = int.max; bEXTREMEDEATH = true; } else if ( target is 'SWWMHangingKeen' ) damage = max(target.Health,damage); // rescued by love :3 else if ( SWWMHDoomHandler.IsCuteGirl(target) ) { // no cute demon girl can resist demo's charm damage = max(target.Health,damage); bNOEXTREMEDEATH = true; } return damage; } override int SpecialMissileHit( Actor victim ) { if ( !victim.bSHOOTABLE && (victim != tracer) ) return 1; if ( tracer && (victim != tracer) ) return 1; return -1; } action void A_HeartTick() { special1++; if ( !(special1%3) && (special2 > 0) ) special2--; A_SetScale(.2+.02*sin(special1*.25*GameTicRate)); double magvel = vel.length(); if ( magvel > 0 ) { Vector3 dir = vel/magvel; vel = dir*min(30,magvel*1.1); } double steppy = vel.length()/4.; for ( int i=2; i<6; i++ ) { Vector3 dir2 = vel.unit(); let t = Spawn("LoveHeartTrail",level.Vec3Offset(pos,-dir2*steppy*i)); t.scale = scale; } int numpt = Random[ExploS](1,3); for ( int i=0; i cl ) LinePart = 0; else LinePart = 1; } else { LinePart = 1; // always middle LineSide = 0; } if ( Blocking3DFloor ) { Sector sec = LineSide?BlockingLine.frontsector:BlockingLine.backsector; for ( int i=0; i con; con.Clear(); con.Push(HitLine); Sector s = LineSide?HitLine.backsector:HitLine.frontsector; int found = 0; do { found = 0; for ( int i=0; i 0 ); for ( int i=0; i con; con.Clear(); con.Push(HitSector); int found; do { found = 0; for ( int i=0; i= con.Size()) ) { found++; con.Push(l.frontsector); } if ( (l.backsector.GetTexture(1) == HitTexture) && (con.Find(l.backsector) >= con.Size()) ) { found++; con.Push(l.backsector); } } } } while ( found > 0 ); for ( int i=0; i con; con.Clear(); con.Push(HitSector); int found; do { found = 0; for ( int i=0; i= con.Size()) ) { found++; con.Push(l.frontsector); } if ( (l.backsector.GetTexture(0) == HitTexture) && (con.Find(l.backsector) >= con.Size()) ) { found++; con.Push(l.backsector); } } } } while ( found > 0 ); for ( int i=0; i PlayerPawn(user.player.mo).UseRange ) return false; if ( user is 'Demolitionist' ) { patter = user; let g = SWWMGesture.SetGesture(Demolitionist(patter),GS_Headpat); if ( !g ) return false; // can't headpat at the moment patting = true; g.pats = self; oldtargettics = target.tics; target.tics = -1; patter.player.cheats |= CF_TOTALLYFROZEN; Demolitionist(patter).scriptedinvul = true; target.bDORMANT = true; if ( SWWMUtility.IdentifyingDog(target) ) SWWMUtility.MarkAchievement("mbf",user.player); if ( SWWMHDoomHandler.IsCuteGirl(target) || SWWMHDoomHandler.IsStaticSexyTime(target) ) SWWMHandler.AddOneliner("pethdoom",2,40); else if ( SWWMHDoomHandler.IsSexyTime(target) ) SWWMHandler.AddOneliner("pethdoomfinish",2,80); return true; } return false; } }