Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
  • 0
Desfar

Monsters that behave like +Ripper

Question

Is it possible to make a monster akin to the lost soul, but that blasts through its targets to the other side?
This would be as a player summon, akin to the summoned Wraiths.
The best I can figure out so far is to try and convert the monster into a missile during its attack, and have it turn back into a monster shortly after. Though this has issues with impact on the walls or ceilings.

Any input or obvious tags I have glossed over?

Share this post


Link to post

15 answers to this question

Recommended Posts

  • 1
Posted (edited)

Giving it the "THRUACTORS" flag on its attack state may work. Try this:

 

Actor LostSoulGhost : LostSoul
{
Translation "168:191=208:223"
Obituary "%o's soul was sucked away by an Orange-flavor Lost Soul"
States
    {
    See:
        SKUL A 0 A_ChangeFlag("THRUACTORS",false)
        goto Super::See
    Missile:
        SKUL C 10 BRIGHT A_FaceTarget
        TNT1 A 0 A_ChangeFlag("THRUACTORS",true)
        SKUL D 4 BRIGHT A_SkullAttack
        SKUL CD 4 BRIGHT A_JumpIfCloser(radius+32,"DamageThru")
        Goto Missile+3
    DamageThru:
        SKUL CCDD 2 BRIGHT A_Explode(8,48,XF_NOTMISSILE|XF_NOSPLASH|XF_THRUSTLESS)
        goto Missile+3
    }
}

I made it orange to be distinguishable from the original lost soul.

Share this post


Link to post
  • 0
Posted (edited)

What if the player's weapon shot a projectile that looked like a lost soul with the pierce flag and spawned a slaved lost soul in its crash state?

 

Edit: that'd be the ripper flag and AAPTR_Master

 

Edit more: that's exactly what you're already describing isn't it? Or are you flipping on and off the monster and projectile flags?

Edited by Nihlith

Share this post


Link to post
  • 0
Posted (edited)

I was looking into flipping the tag. Actively working on it today.
I was gonna set it to do a distance measurement to flip the tag from missile back to monster.

Im not super savy on the Master setups, so ill do some more digging into it.
It seems like it could be the solution to set my 'missile projectile' back into a monster when it hits a wall. 
It could work well to have the monster spawn a projectile, then reappear back at the end of the projectile (crash or duration) though i need to figure out how to transfer its health/duration.

I guess that should be my new question, of How to pass on the Health of the monster to the Crash state monster that appears after the projectile stops
Edit : Getting the feel that A_SetUserVar is likely gonna be my method, just gotta figure out how to use it.



But ideally it would be like a more dynamic and hostile Wraith that can dip through enemies in larger hordes.

Edited by Desfar

Share this post


Link to post
  • 0

I couldn't say. I just went to great lengths to rebuild something because I couldn't figure out how to transfer characteristics  between actors and their spawn. Why is important that the projectile and the monster have the same HP pool? 

Share this post


Link to post
  • 0

I don't know if this helps but I found this old thread. Maybe you can make use of the +SKULLFLY flag?:

 

 

Share this post


Link to post
  • 0

I would just have it drop a projectile each frame that lasts 1 frame.  Have it detect the distance to its target when it starts and ends it's attack so it can snap in and out of its ripper state. That's how I would approach it

Share this post


Link to post
  • 0
Posted (edited)

Best solution I'm working on is to make the Monster warp to the projectile after it goes so many frames, or until it crashes.
Trying to Bastardize some code elements from some Headshot Code I saved.
so its looking like
MONS A 4 Shoot Tele-Rippa-Missle //also set the missile as the master

TNT1 A 10 //set invis for a few frames as the bullet wraith continues the animation
TNT1 A 0 a_warp // jumps the monster wraith to the projectile wraith.

The projectile will likely need to find some way to remain 'alive' through its crash state, which depends if the warp state will allow it to be jumped to if its still in the 'crash' state.

Any massive flaws to the logic of this one so far?

EDIT: Got it partially working. Main issue is the projectiles spawning downwards. Trying to figure out how to make the aiming work a little better. But the monster DOES vanish and reappear.

Spoiler

ACTOR SummonSpirit
{
  Health 100
  Radius 8
  Height 16
  Mass 50
  Speed 8
  Damage 3
  PainChance 256
  Monster
  +FLOAT
  +NOGRAVITY
  +MISSILEMORE
  +DONTFALL
  +NOICEDEATH
  +Friendly
  +Ripper
  AttackSound "skull/melee"
  PainSound "skull/pain"
  DeathSound "skull/death"
  ActiveSound "skull/active"
  RenderStyle SoulTrans
  Obituary "$OB_SKULL" // "%o was spooked by a lost soul."
  States
  {
  Spawn:
    PSPE AABB 2 Bright A_Look
    Loop
  See:
    PSPE AB 4 Bright A_Chase
    Loop
  Missile:
    tnt1 a 0 a_Facetarget
    PSPE AB 4 Bright A_CustomMissile("GhostRipperteleport", 0, 0, 0, 0, 0, SXF_SetMaster)
    tnt1 A 19  
    PSPE A 1 A_Warp (AAPTR_Master, 0, 0, 0, 0, WARPF_Interpolate | WARPF_NoCheckPosition)
    PSPE BA 4 Bright
    GoTo See
  Pain:
    PSPE A 3 Bright
    PSPE B 3 Bright A_Pain
    Goto See
  Death:
    SPIR D 4
    SPIR E 4 A_Scream
    SPIR FGHI 4
    Stop
  }
}

ACTOR GhostRipperteleport
{
  Radius 6
  Height 8
  Speed 15
  sCALE .6
  +NOGRAVITY
  FastSpeed 30
  Damage 3
  Projectile
  RenderStyle Add
  Alpha 1
  States
  {
  Spawn:
    TNT1 A 0 
    BAL2 A 20 Bright
    STOP
  Death:
    FBSI CDC 6 Bright
    Stop
  }
}

 

Edited by Desfar

Share this post


Link to post
  • 0

No that sounds pretty smart, and you don't wind up with problems involving the monster getting stuck during charge, and leaves the melee attack free.  Gives a lot of flexibility for variants.

Share this post


Link to post
  • 0
58 minutes ago, Burgish said:

No that sounds pretty smart, and you don't wind up with problems involving the monster getting stuck during charge, and leaves the melee attack free.  Gives a lot of flexibility for variants.

Only once I get it working, lmao.

This'll be one of the few items for my mod that doesn't directly call to other ingrained mechanics.

So I can likely post a functionalish version at the end.

And get roasted for my chimp code. 

Share this post


Link to post
  • 0

Once it works it won't matter what it's lineage is. Apes together strong. 

Share this post


Link to post
  • 0
15 hours ago, Gothic said:

Giving it the "THRUACTORS" flag on its attack state may work. Try this:

Spoiler

Actor LostSoulGhost : LostSoul
{
Translation "168:191=208:223"
Obituary "%o's soul was sucked away by an Orange-flavor Lost Soul"
States
    {
    See:
        SKUL A 0 A_ChangeFlag("THRUACTORS",false)
        goto Super::See
    Missile:
        SKUL C 10 BRIGHT A_FaceTarget
        TNT1 A 0 A_ChangeFlag("THRUACTORS",true)
        SKUL D 4 BRIGHT A_SkullAttack
        SKUL CD 4 BRIGHT A_JumpIfCloser(radius+32,"DamageThru")
        Goto Missile+3
    DamageThru:
        SKUL CCDD 2 BRIGHT A_Explode(8,48,XF_NOTMISSILE|XF_NOSPLASH|XF_THRUSTLESS)
        goto Missile+3
    }
}

I made it orange to be distinguishable from the original lost soul.

 

You son of a very nice lady.
That's exactly right. and of course it was as easy as a flag I had overlooked.
I was still struggling with my initial concept for 2 hours this morning before i gave up and tried yours.

Share this post


Link to post
  • 0

I tried to create this ghost soul in ZScript.

 

It charges through the target and stops after a little distance later, doing same damage as normal lost soul (random(1,8) * damage prop). Damages targets once per charge, no explosion. Does not go through solid non-shootable actors and actors with +DONTRIP. After attack is done, it keeps list of monsters that are in its hitbox and ignores collisions with them, so it does not get stuck. Once out of their hitbox they are removed on that list.

 

Works for me. :)

 

class LostSoulGhost : LostSoul
{
	default
	{
		Translation "168:191=208:223";
	}
	
	States
	{
	See:
		SKUL AB 6 BRIGHT A_GhostSkullChase;
		Loop;
	Pain:
		SKUL E 0 {charging = false;}
		Goto super::Pain;
	Missile:
		SKUL C 10 BRIGHT A_FaceTarget;
		SKUL D 0 BRIGHT A_GhostSkullAttack;
		SKUL DDDDCCCC 1 BRIGHT A_GhostSkullFly;
		Goto Missile+2;
	}
	
	array<Actor> hitlist;
	vector3 skulvel;
	bool charging;
	actor htarget;
	
	void A_GhostSkullChase()
	{
		charging = false;
		for (int i = 0; i < hitlist.size(); i++)	// clear things that are not in our hitbox anymore from the list
		{
			if (!CheckCollision(hitlist[i]))
			{
				hitlist[i] = hitlist[hitlist.size() - 1];
				hitlist.pop();
				i--;
			}
		}
		
		if (hitlist.size() == 0)	// does not attack while it is inside something's hitbox
			A_Chase();
		else
			A_Wander();
	}
	
	void A_GhostSkullAttack(double skullspeed = 20)
	{
		if (!target) return;
		
		charging = true;
		hitlist.clear();
		htarget = null;
		if (skullspeed <= 0) skullspeed = 20;
		
		A_StartSound(attackSound, CHAN_VOICE);
		A_FaceTarget();
		
		skulvel = (skullspeed * cos(angle), 
				skullspeed * sin(angle), 
				(target.pos.z + target.height/2 - pos.z) / DistanceBySpeed(target, skullspeed));
		
		vel.x = 0;
		vel.y = 0;
		vel.z = skulvel.z;
	}
	
	void A_GhostSkullFly(statelabel resetState = "See")
	{
		if (!charging || vel.xy.length() > 4.0)	// if something externally thrust us enough, stop the charging
		{
			charging = false;
			vel.z = 0;
			SetStateLabel(resetState);
			return;
		}
		
		vel.x = 0;
		vel.y = 0;
		vector2 velxy = skulvel.xy;
		int len = velxy.length();
		vector2 unit = velxy.unit();
		for (int i = 0; i < len; i++)
		{
			bool mres = TryMove(Vec2Offset(unit.x, unit.y), 1);
			if (!mres || (htarget && !CheckCollision(htarget, 16)))	// stop after we hit a wall or unrippable thing, or after passing through intended target
			{
				let it2 = BlockThingsIterator.Create(self, radius + 2);
				while (it2.Next())
				{
					DamageActor(it2.thing, 2, false);
				}
				charging = false;
				vel.z = 0;
				SetStateLabel(resetState);
				return;
			}
			
			let it = BlockThingsIterator.Create(self);
			while (it.Next())	// damage things that we pass through, which were not damaged yet
			{
				DamageActor(it.thing, 0, true);
			}
		}
	}
	
	void DamageActor(Actor mo, double plusrad = 0, bool thru = false)
	{
		if (mo == self || !mo.bShootable || mo.health <= 0) return;
		if (!CheckCollision(mo, plusrad)) return;
		if (hitlist.Find(mo) < hitlist.size()) return;
		mo.DamageMobj(self, self, damage * random[slam](1, 8), "Melee");
		hitlist.push(mo);
				
		if (thru)
		{
			hitlist.push(mo);
			if (mo == target) htarget = mo;
		}
	}
	
	bool CheckCollision(Actor other, double plusrad = 0)
	{
		if (!other) return false;
		Vector3 vdiff = level.Vec3Diff(pos, other.pos);

		if (abs(vdiff.x) >= radius + other.radius + plusrad) return false;
		if (abs(vdiff.y) >= radius + other.radius + plusrad) return false;
		if (-vdiff.z >= other.height + plusrad) return false;
		if (vdiff.z >= height + plusrad) return false;

		return true;
	}
	
	override bool CanCollideWith(Actor other, bool passive)
	{
		// do not get stuck after charging inside things we hit on the way.
		if ((!passive || !other.player) && hitlist.find(other) < hitlist.size()) return false;		
		
		// do not stop during charging if we hit something that can be ripped through
		if (!passive && charging && other.bShootable && !other.bDontRip) return false;
		
		return true;
	}
}

 

 

 

Share this post


Link to post
  • 0

Working on fine tuning the Code right now.
Got the ghost semi functional, and added a self harm code so that it dies after a short while.
Now I just need to add the modifications to the corpse system so that a monster corpse explodes into 2 or 3 of these ghosts.

And of course the delivery system to get this 'token' to the corpses.
Likely a Railgun that makes an explosion at the crash point and gives the token to all nearby bodies.

Share this post


Link to post
  • 0
Posted (edited)

Partially workable .Wad
Im not very experienced at making these things an easy plug and play.
But heres my crappy 0.8 alpha of the chain gun replacement/summonable spectre (Just a blood head for the moment)
Much finetuning to come. Again, big ups to Gothic for the tag!
Edit: Made an effort to try and make it work out of the box

 

CRUDEDESWEAPON.zip

Edited by Desfar

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×