Neutral monster

Moderator: GZDoom Developers

User avatar
MartinHowe
Posts: 2022
Joined: Mon Aug 11, 2003 1:50 pm
Location: Waveney, United Kingdom
Contact:

Re: Neutral monster

Post by MartinHowe »

This has been undergoing testing as part of a bigger work for now:

Code: Select all

// --- BLACKCAT - 15898 --------------------------------------------------------

ACTOR BlackCat 15898
{
//
/// Black Cat
/// =========
/// Class Name              : BlackCat
/// DoomEdNum               : 15898
/// Formal Name             : Black Cat
/// Type                    : Animal
/// Group                   : Pesticide
/// Melee Attack            : Scratch
/// Missile Attack          : None
/// Drop Item When Killed   : None
/// Description             :
/// ...
/// ... A black cat that can be friendly, neutral or hostile and supports many
/// ... special effects via scripting and the USESPECIAL flag.
/// ...
/// ... To make the cat neutral so that he ignores both players and monsters
/// ... unless hit or panicked by gunfire, give the cat a BlackCatNeutralFlag
/// ... for his inventory and set the FRIENDLY flag. In this state, his idling
/// ... actions are limited, but this is because of engine limitations that
/// ... at the time of writing cannot be completely overcome by coding.
/// ...
/// ... To make the cat hostile to players, take any BlackCatNeutralFlag from
/// ... his inventory and clear the FRIENDLY flag.
/// ...
/// ... To make the cat hostile to monsters and friendly to players, take any
/// ... BlackCatNeutralFlag from his inventory and set the FRIENDLY flag.
/// ...
/// ... To make the cat hostile to everything is not yet implemented; it will
/// ... require a lot of extra coding and may not be truly reliable, given the
/// ... current engine limitations. For the moment, never clear the FRIENDLY
/// ... flag when the cat has no BlackCatNeutralFlag in his inventory; this has
/// ... never been tested and is most definitely NOT SUPPORTED at this time.
/// ...
/// ... By default the cat is neutral and is coded to jump to the purr state
/// ... when idling, if given a BlackCatUsedFlag for his inventory; this would
/// ... normally be accomplished by a script via the USESPECIAL flag, so that
/// ... you can pet the cat and he will purr for a short time in response.
/// ...
/// ... This cat is an extended version of those in the Bible of Blasphemy and
/// ... could easily be subclassed in many different ways to do many different
/// ... things; the same logic could also be adapted to the NAZI dogs as well.
/// ...
/// Idea                    : Yellow key in AlienDOOM III : Aliens vs Predator
/// Source                  : Mr Jones sprites modified, recoloured and edited
/// Credit                  : Michael Ghummelt
//
//$Category BUTCHERY
//$Sprite BCATA2A8
//
	Radius 10
	Height 15
	Mass 40
	Speed 15
	MaxStepHeight 80
	MaxDropoffHeight 128
	Health 100
	PainChance 100
	MeleeDamage 4
	Obituary "%o's path was crossed by a black cat."
//	SeeSound "blackcat/sight"
	MeleeSound "blackcat/attack"
	PainSound "blackcat/pain"
	DeathSound "blackcat/death"
	ActiveSound "blackcat/active"
	MONSTER
	-CANUSEWALLS
	+FLOORCLIP
	+DROPOFF
	+LOOKALLAROUND
	+FRIENDLY
	+USESPECIAL
	States
	{
	//
	// Idling sprite phases are BCAS {LETTER}. Ln means
	// tail lash: 0 - down, 1 - partly up, 2 - fully up.
	//
	// Only difference between LASH and WHIP is speed,
	// the sprites are the same, just different timings.
	//
	// A eyes open    L0  none  (head up)
	// B eyes open    L1  none  (head up)
	// C eyes open    L2  none  (head up)
	// D eyes open    L0  lick  (head partly down)
	// E eyes open    L1  lick  (head partly down)
	// F eyes open    L2  lick  (head partly down)
	// G eyes open    L0  slurp (head fully down)
	// H eyes open    L1  slurp (head fully down)
	// I eyes open    L2  slurp (head fully down)
	// J eyes closed  L0  none  (head up)
	// K eyes closed  L1  none  (head up)
	// L eyes closed  L2  none  (head up)
	// M eyes closed  L0  lick  (head partly down)
	// N eyes closed  L1  lick  (head partly down)
	// O eyes closed  L2  lick  (head partly down)
	// P eyes closed  L0  slurp (head fully down)
	// Q eyes closed  L1  slurp (head fully down)
	// R eyes closed  L2  slurp (head fully down)
	//
	Spawn:
		BCAT A  1
		BCAT A  0 A_TakeInventory("BlackCatBoredomCounter", 2147483647)
		BCAT A  0 A_GiveInventory("BlackCatNeutralFlag", 1)
	Idle:
		BCAS A  8 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS A  8 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS A  0 A_JumpIfInventory("BlackCatUsedFlag", 1, "IdlePurr")
		BCAS A  0 A_JumpIfInventory("BlackCatCoolFlag", 1, "IdleCool")
		BCAS A  0 A_Jump(160, "IdleStill")	// eyes open, no lash/whip/lick/slurp/purr
		BCAS A  0 A_Jump(104, "IdleLick")	// eyes open, no lash/whip
		BCAS A  0 A_Jump(160, "IdleSlurp")	// eyes open, no lash/whip
		BCAS A  0 A_Jump(170, "IdleLash")	// eyes open, no lick/slurp/purr
		BCAS A  0 A_Jump(180, "IdleWhip")	// eyes open, no lick/slurp/purr
		BCAS A  0 A_Jump(256, "IdlePurr")	// eyes open, no lash/whip
		Goto IdleStill						// jump should never be taken
	IdleCool:
		BCAS A  0 A_Jump(160, "IdleStill")	// eyes open, no lash/whip/lick/slurp/purr
		BCAS A  0 A_Jump(170, "IdleLash")	// eyes open, no lick/slurp/purr
		BCAS A  0 A_Jump(256, "IdleWhip")	// eyes open, no lick/slurp/purr
		Goto IdleStill						// jump should never be taken
	//// SEE ENTER VALIDATION //////////////////////////
		/**** IDENTIFY CONDITION AND HANDLE IT ********/
	IdleSightInit:
		// check for target (and resolve if probably not)
		BCAT A  0 A_JumpIfCloser(32767, "IdleChaseCheck")
		BCAT A  0 A_ClearTarget // resolve in usual way
		Goto IdlePanicCheck
		// got a target
	IdleChaseCheck:
		BCAT A  0 A_JumpIfInventory("BlackCatNeutralFlag", 1, "IdleChaseNeutral")
		Goto IdleChaseAttack
		// not got a target
	IdlePanicCheck:
		BCAT A  0 A_JumpIfInventory("BlackCatNeutralFlag", 1, "IdlePanicNeutral")
		Goto IdlePanicAttack
		/**** GOT TARGET AND NOT NEUTRAL **************/
	IdleChaseAttack:
		BCAT A  0 A_PlaySound("blackcat/sight")
		BCAT A  0 A_GiveInventory("BlackCatSeeFlag", 1)
		Goto See
		/**** GOT TARGET BUT NEUTRAL ******************/
	IdleChaseNeutral:
		// This block explicitly takes all 4 see flags,
		// because it can also be called from one of the
		// see state handlers, SeeChase, if the cat is
		// attacked while in this logical condition.
		BCAT A  0 A_ClearTarget
		BCAT A  8 A_TakeInventory("BlackCatSeeFlag", 4)
		BCAT A  8 // prevents potential race condition
		Goto Idle
		/**** GOT NO TARGET AND NOT NEUTRAL ***********/
	IdlePanicAttack:
		BCAT A  0 A_GiveInventory("BlackCatSeeFlag", 2)
		Goto See
		/**** GOT NO TARGET AND NEUTRAL ***************/
	IdlePanicNeutral:
		BCAT A  0 A_GiveInventory("BlackCatSeeFlag", 3)
		Goto See
	//// STILL /////////////////////////////////////////
	IdleStill:
		BCAS A  8 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS A  8 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		Goto Idle
	//// LASH //////////////////////////////////////////
	IdleLash:
		BCAS B  0 A_TakeInventory("BlackCatActionCounter", 2147483647)
		BCAS B  0 A_Jump(170, "IdleLashGive1")
		BCAS B  0 A_Jump(170, "IdleLashGive2")
		BCAS B  0 A_Jump(200, "IdleLashGive3")
		BCAS B  0 A_Jump(256, "IdleLashGiveX")
	IdleLashGive1:
		BCAS B  0 A_GiveInventory("BlackCatActionCounter", 1)
		Goto IdleLashLoop
	IdleLashGive2:
		BCAS B  0 A_GiveInventory("BlackCatActionCounter", 2)
		Goto IdleLashLoop
	IdleLashGive3:
		BCAS B  0 A_GiveInventory("BlackCatActionCounter", 3)
		Goto IdleLashLoop
	IdleLashGiveX:
		BCAS B  0 A_GiveInventory("BlackCatActionCounter", Random(4, 8))
//		Goto IdleLashLoop
	IdleLashLoop:
		BCAS B  0 A_JumpIfInventory("BlackCatActionCounter", 1, "IdleLashTick")
		Goto IdleLashEnd
	IdleLashTick:
		BCAS B  0 A_TakeInventory("BlackCatActionCounter", 1)
	IdleLashAction:
		BCAS B  7 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS C  5 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS C  5 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS C  5 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS C  5 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS B  5 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS A  8 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS A  8 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS A  8 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS A  8 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		Goto IdleLashLoop
	IdleLashEnd:
		BCAS A  8 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS A  8 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS A  8 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS A  8 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		Goto Idle
	//// WHIP //////////////////////////////////////////
	IdleWhip:
		BCAS B  0 A_TakeInventory("BlackCatActionCounter", 2147483647)
		BCAS B  0 A_Jump(170, "IdleWhipGive1")
		BCAS B  0 A_Jump(170, "IdleWhipGive2")
		BCAS B  0 A_Jump(170, "IdleWhipGiveX")
		BCAS B  0 A_Jump(256, "IdleWhipGive3")
	IdleWhipGive1:
		BCAS B  0 A_GiveInventory("BlackCatActionCounter", 1)
		Goto IdleWhipLoop
	IdleWhipGive2:
		BCAS B  0 A_GiveInventory("BlackCatActionCounter", 2)
		Goto IdleWhipLoop
	IdleWhipGive3:
		BCAS B  0 A_GiveInventory("BlackCatActionCounter", 3)
		Goto IdleWhipLoop
	IdleWhipGiveX:
		BCAS B  0 A_GiveInventory("BlackCatActionCounter", Random(4, 8))
//		Goto IdleWhipLoop
	IdleWhipLoop:
		BCAS B  0 A_JumpIfInventory("BlackCatActionCounter", 1, "IdleWhipTick")
		Goto IdleWhipEnd
	IdleWhipTick:
		BCAS B  0 A_TakeInventory("BlackCatActionCounter", 1)
	IdleWhipAction:
		BCAS B  4 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS C  9 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS B  3 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS A  8 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS A  8 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		Goto IdleWhipLoop
	IdleWhipEnd:
		BCAS A  8 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS A  8 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS A  8 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS A  8 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		Goto Idle
	//// LICK //////////////////////////////////////////
	IdleLick:
		BCAS D  0 A_TakeInventory("BlackCatActionCounter", 2147483647)
		BCAS D  0 A_Jump(170, "IdleLickGive3")
		BCAS D  0 A_Jump(170, "IdleLickGive2")
		BCAS D  0 A_Jump(170, "IdleLickGiveX")
		BCAS D  0 A_Jump(256, "IdleLickGive1")
	IdleLickGive1:
		BCAS D  0 A_GiveInventory("BlackCatActionCounter", 1)
		Goto IdleLickLoop
	IdleLickGive2:
		BCAS D  0 A_GiveInventory("BlackCatActionCounter", 2)
		Goto IdleLickLoop
	IdleLickGive3:
		BCAS D  0 A_GiveInventory("BlackCatActionCounter", 3)
		Goto IdleLickLoop
	IdleLickGiveX:
		BCAS D  0 A_GiveInventory("BlackCatActionCounter", Random(4, 5))
//		Goto IdleLickLoop
	IdleLickLoop:
		BCAS D  0 A_JumpIfInventory("BlackCatActionCounter", 1, "IdleLickTick")
		Goto IdleLickEnd
	IdleLickTick:
		BCAS D  0 A_TakeInventory("BlackCatActionCounter", 1)
	IdleLickAction:
		BCAS D  0 A_PlaySound("blackcat/lick")
		BCAS D  9 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS D  9 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		Goto IdleLickLoop
	IdleLickEnd:
		BCAS A  9 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS A  9 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		Goto Idle
	//// SLURP /////////////////////////////////////////
	IdleSlurp:
		BCAS A  0 A_TakeInventory("BlackCatActionCounter", 2147483647)
		BCAS A  0 A_Jump(170, "IdleSlurpGive3")
		BCAS A  0 A_Jump(170, "IdleSlurpGive2")
		BCAS A  0 A_Jump(170, "IdleSlurpGiveX")
		BCAS A  0 A_Jump(256, "IdleSlurpGive1")
	IdleSlurpGive1:
		BCAS A  0 A_GiveInventory("BlackCatActionCounter", 1)
		Goto IdleSlurpLoop
	IdleSlurpGive2:
		BCAS A  0 A_GiveInventory("BlackCatActionCounter", 2)
		Goto IdleSlurpLoop
	IdleSlurpGive3:
		BCAS A  0 A_GiveInventory("BlackCatActionCounter", 3)
		Goto IdleSlurpLoop
	IdleSlurpGiveX:
		BCAS A  0 A_GiveInventory("BlackCatActionCounter", Random(4, 5))
//		Goto IdleSlurpLoop
	IdleSlurpLoop:
		BCAS A  0 A_JumpIfInventory("BlackCatActionCounter", 1, "IdleSlurpTick")
		Goto IdleSlurpEnd
	IdleSlurpTick:
		BCAS A  0 A_TakeInventory("BlackCatActionCounter", 1)
	IdleSlurpAction:
		BCAS A  0 A_PlaySound("blackcat/slurp")
		BCAS A  2 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS D  6 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS G  9 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS D  3 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS A  9 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		Goto IdleSlurpLoop
	IdleSlurpEnd:
		BCAS A  9 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS A  9 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		Goto Idle
	//// PURR //////////////////////////////////////////
	IdlePurr:
		BCAS A  0 A_TakeInventory("BlackCatUsedFlag", 1)
		BCAS A  0 A_TakeInventory("BlackCatActionCounter", 2147483647)
		BCAS A  0 A_Jump(170, "IdlePurrGive3")
		BCAS A  0 A_Jump(170, "IdlePurrGive4")
		BCAS A  0 A_Jump(170, "IdlePurrGive5")
		BCAS A  0 A_Jump(256, "IdlePurrGiveX")
	IdlePurrGive3:
		BCAS A  0 A_GiveInventory("BlackCatActionCounter", 3)
		Goto IdlePurrLoop
	IdlePurrGive4:
		BCAS A  0 A_GiveInventory("BlackCatActionCounter", 4)
		Goto IdlePurrLoop
	IdlePurrGive5:
		BCAS A  0 A_GiveInventory("BlackCatActionCounter", 5)
		Goto IdlePurrLoop
	IdlePurrGiveX:
		BCAS A  0 A_GiveInventory("BlackCatActionCounter", Random(6, 9))
//		Goto IdlePurrLoop
	IdlePurrLoop:
		BCAS A  0 A_JumpIfInventory("BlackCatActionCounter", 1, "IdlePurrTick")
		Goto IdlePurrEnd
	IdlePurrTick:
		BCAS A  0 A_TakeInventory("BlackCatActionCounter", 1)
	IdlePurrAction:
		BCAS A  0 A_PlaySound("blackcat/purr")
		BCAS A  9 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS A  9 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS A  9 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS A  9 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS A  9 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		Goto IdlePurrLoop
	IdlePurrEnd:
		BCAS A  7 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS A  7 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		BCAS A  7 A_LookEx(0, 0, 0, 0, 0, "IdleSightInit")
		Goto Idle

	See:
		//
		// If Puss can't find a target, he gets bored
		// after a while and give up, like a real cat.
		//
		// There is no A_JumpIfHasTarget, so we just use
		// JumpIfCloser(infinity, ...) and give infinity
		// as 32767; the codepointer uses a fixed_t for
		// the distance and cannot handle large values
		// such as 2147483647 (INT_MAX for 32 bits).
		//
		// Most maps are well short of 32767 units; it
		// is still a kludge, as some might be bigger.
		//
		// Skip new target check if in panic mode and
		// neutral for the first time; just note it.
	SeeCheckPanicNeutral:
		BCAT C  0 A_JumpIfInventory("BlackCatSeeFlag", 4, "SeeCheckTarget")			// subsequent time/hit by monster/re-panicked
		BCAT C  0 A_JumpIfInventory("BlackCatSeeFlag", 3, "SeeCheckPanicNotice")	// first time
		Goto SeeCheckTarget
	SeeCheckPanicNotice:
		// Recognise new condition and do NOT process
		// target check upon the first such iteration.
		BCAT C  0 A_GiveInventory("BlackCatSeeFlag", 1)	// acknowledge, but skip target check THIS time
		Goto SeeLook
	SeeCheckTarget:
		// Got a target who is reasonably close? If not,
		// still looking for a target or logical target
		// is right over on the other side of the map. A
		// real cat gets bored quite easily; it's safest
		// to resolve this as just not having a target.
		BCAT C  0 A_JumpIfCloser(32767, "SeeChase")
		BCAT C  0 A_ClearTarget
	SeeLook:
	//// JUST LOOKING FOR A TARGET /////////////////////
		// Also clear the "used" flag here; it may have
		// been set and the animal then alerted before
		// the idle state could properly deal with it.
		BCAT C  0 A_TakeInventory("BlackCatUsedFlag", 1)
		// Boredom sets in if there has been no target
		// for a while, so check for that condition.
	SeeLookCheckBored:
		BCAT C  0 A_JumpIfInventory("BlackCatBoredomCounter", 0, "SeeBored")
		BCAT C  0 A_Jump(224, "SeeLookTick3")
		BCAT C  0 A_Jump(170, "SeeLookTick2")
	SeeLookTick1:
		BCAT C  0 A_GiveInventory("BlackCatBoredomCounter", 1)
	SeeLookTick2:
		BCAT C  0 A_GiveInventory("BlackCatBoredomCounter", 1)
	SeeLookTick3:
		BCAT C  0 A_GiveInventory("BlackCatBoredomCounter", 1)
	SeeLookCheckMode:
		// Check for 4. If still 3, probably repeated
		// hit on cat. If so, player must have hit it;
		// in that case should still panic neutral.
		BCAT C  0 A_JumpIfInventory("BlackCatSeeFlag", 4, "SeeLookPanicNeutral")
		BCAT C  0 A_JumpIfInventory("BlackCatSeeFlag", 3, "SeeCheckPanicNotice")
	SeeLookChase:
		BCAT C  2 A_Chase
		BCAT C  2 A_Chase
		BCAT D  2 A_Chase
		BCAT D  2 A_Chase
		BCAT D  0 A_TakeInventory("BlackCatSeeFlag", 4)
		Goto See
	SeeLookPanicNeutral:
		BCAT C  2 A_Wander
		BCAT C  2 A_Wander
		BCAT D  2 A_Wander
		BCAT D  2 A_Wander
		Goto See
	SeeChase:
	//// ACTUALLY CHASING A TARGET /////////////////////
		// If wandering and hit by unfriendly fire, the
		// see flag value will be 4, which means ignore
		// the attack and go back to being idle.
		BCAT C  0 A_JumpIfInventory("BlackCatSeeFlag", 4, "IdleChaseNeutral")
		// Also clear the "used" flag here; it may have
		// been set and the animal then alerted before
		// the idle state could properly deal with it.
		BCAT C  0 A_TakeInventory("BlackCatUsedFlag", 1)
		BCAT C  0 A_TakeInventory("BlackCatBoredomCounter", 2147483647)
		BCAT C  2 A_Chase
		BCAT C  2 A_Chase
		BCAT D  2 A_Chase
		BCAT D  2 A_Chase
		BCAT D  0 A_TakeInventory("BlackCatSeeFlag", 4)
		Goto See
	//// BORED /////////////////////////////////////////
	SeeBored:
		// Do not clear the "used" flag here; it can be
		// left for the subsequent idle state to handle.
//		BCAT C  0 A_TakeInventory("BlackCatUsedFlag", 1)
		BCAS C  0 A_TakeInventory("BlackCatBoredomCounter", 2147483647)
		BCAS C  0 A_ClearTarget
		BCAT C  0 A_TakeInventory("BlackCatSeeFlag", 4)
		Goto Idle

	Melee:
		BCAT E  0 A_TakeInventory("BlackCatBoredomCounter", 2147483647)
		BCAT E  8 A_FaceTarget
		BCAT F  8 A_MeleeAttack
		BCAT E  8 A_FaceTarget
		BCAT F  8 A_MeleeAttack
		Goto See

	Pain:
		BCAT G  0 A_TakeInventory("BlackCatBoredomCounter", 2147483647)
		BCAT G  3
		BCAT H  3 A_Pain
		Goto See

	Death:
		BCAT I  0 A_TakeInventory("BlackCatBoredomCounter", 2147483647)
		BCAT I  4
		BCAT J  4 A_Scream
		BCAT K  4 A_Fall
		BCAT L  4
		BCAT M  4
		BCAT N  4
		BCAT O  4
		BCAT P  4
	Dead:
		BCAT Q -1
		Stop

	XDeath:
		BCAT R  0 A_TakeInventory("BlackCatBoredomCounter", 2147483647)
		BCAT R  5
		BCAT S  5 A_XScream
		BCAT T  5 A_Fall
		BCAT U  5
		BCAT V  5
		BCAT W -1
		Stop

	Raise:
		BCAT Q  0 A_TakeInventory("BlackCatBoredomCounter", 2147483647)
		BCAT Q  5
		BCAT P  5
		BCAT O  5
		BCAT N  5
		BCAT M  5
		BCAT L  5
		BCAT K  5
		BCAT J  5
		BCAT I  5
		Goto See
	}
}

ACTOR BlackCatSeeFlag : Inventory
{
//
// The cat is given one of these by the see state
// precheck and cleared when he enters the idle state.
//
// You can use it to determine if the cat was explicitly
// put into the see state via a call to A_LookEx or via
// an engine-initiated state jump (Raise, Pain, etc.).
//
// 0 = see state entered implicitly
// 1 = see state entered explicitly with target (and not neutral)
// * * [impossible] see state entered explicitly with target and neutral
// 2 = see state entered explicitly without target (and not neutral)
// 3 = see state entered explicitly without target and neutral
// 4 = as 4 but after see state recognises the condition
//
	Inventory.Amount 1
	Inventory.MaxAmount 4
}

ACTOR BlackCatNeutralFlag : Inventory
{
//
// The cat can be given or divested of one of these by a
// script. If one is present in his inventory, the cat
// will ignore unfriendly monsters unless attacked.
//
// There is a limitation in that he only does one or two
// frames of each idling animation in this situation. It
// has long and complex reasons; but essentially, there
// must be a "look" codepointer in the idling states or
// else the cat never enters the pain state when hurt;
// since there is no way to make the pain state jump a
// return-state-save call, the pain state and see state
// precheck logic cannot know to which state to return.
//
// All in all, it is a limitation of the current state
// of the engine; fortunately, since cats tend to keep a
// watchful eye on potential hazards, that is what seems
// to the player to be happening. If this technique is
// used on actors with only the usual short idling state
// sequence, it is much easier to hide the effect.
//
	Inventory.Amount 1
	Inventory.MaxAmount 1
}

ACTOR BlackCatUsedFlag : Inventory
{
//
// The cat can be given one of these by a script if he
// is used via USESPECIAL. This cat purrs when used,
// i.e., you can now "pet" a cat in DOOM! Yee-Haaaaaaa!
//
// Of course if you subclass the cat, you can probably
// find even stranger things to do with this flag :)
//
	Inventory.Amount 1
	Inventory.MaxAmount 1
}

ACTOR BlackCatCoolFlag : Inventory
{
//
// The cat can be given or divested of one of these by a
// script. If one is present in his inventory, the cat
// will only commit those idling actions that are quiet
// and involve him looking serenely out at the world; in
// other words, he becomes a real cool cat - chill, man!
//
	Inventory.Amount 1
	Inventory.MaxAmount 1
}

ACTOR BlackCatActionCounter : Inventory
{
//
// This counter is used to determine how many iterations
// of behaviours such as licking and tail-lashing should
// be performed during one sequence of those actions.
//
	Inventory.Amount 1
	Inventory.MaxAmount 2147483647
}

ACTOR BlackCatBoredomCounter : Inventory
{
//
// This counter is used to determine how many iterations
// of the See state should be performed without a target
// being found before puss gets bored and gives up.
//
// The MaxAmount property should be set to about 120% of
// the desired value; the extra 20% is to give room for
// the random extra delay used to make the exact boredom
// time threshold a bit unpredictable (like real cats).
//
	Inventory.Amount 1
	Inventory.MaxAmount 128
}
Gez
 
 
Posts: 17833
Joined: Fri Jul 06, 2007 3:22 pm

Re: Neutral monster

Post by Gez »

Aren't the Strife peasants neutral already? They do retaliate when you hit them.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49056
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: Neutral monster

Post by Graf Zahl »

No. They are nominally hostile but they don't use any offensive AI so the retaliative attack is the only thing you will see from them.
User avatar
DBThanatos
Posts: 3101
Joined: Fri Apr 14, 2006 3:17 pm
Location: in "the darkness that lurks in our mind"
Contact:

Re: Neutral monster

Post by DBThanatos »

MartinHowe wrote:This has been undergoing testing as part of a bigger work for now:

Code: Select all

// --- BLACKCAT - 15898 --------------------------------------------------------
... an enormous code
That's an incredibly long code for one little cat! I guess some of it could be deleted if something like "+neutral" existed.
User avatar
Nash
 
 
Posts: 17433
Joined: Mon Oct 27, 2003 12:07 am
Location: Kuala Lumpur, Malaysia
Contact:

Re: Neutral monster

Post by Nash »

DBThanatos wrote: That's an incredibly long code for one little cat! I guess some of it could be deleted if something like "+neutral" existed.
You'd be surprised how much one little cat can affect one person's life... :mrgreen:
User avatar
MartinHowe
Posts: 2022
Joined: Mon Aug 11, 2003 1:50 pm
Location: Waveney, United Kingdom
Contact:

Re: Neutral monster

Post by MartinHowe »

DBThanatos wrote:That's an incredibly long code for one little cat! I guess some of it could be deleted if something like "+neutral" existed.
:)

The cat's exact behavior as I want it, rather than as I have had to approximate it, should be this:

(1) +FRIENDLY but does NOT attack non-friendly monsters on sight, ONLY if hit by one.
(2) If hit by player/friendly monster, attacks player/friendly monster until killed or kills player/friendly monster or player/friendly monster escapes somewhere the cat can't find him before cat gets bored. Then revert to neutral.
(3) Option to run away from player/friendly monster if hit by one.
(4) Option to run away from monsters if hit by one.

I guess a basic +NEUTRAL flag would do (1) only. For the rest, a +STICKYHITBYPLAYER flag would be useful - the engine should set it if the cat gets hit by a player and the coder has the responsibility of turning it off. Anything else would have to WFDS.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49056
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: Neutral monster

Post by Graf Zahl »

DBThanatos wrote: That's an incredibly long code for one little cat! I guess some of it could be deleted if something like "+neutral" existed.

You'd be surprised how non-trivial that is...
CaptainToenail
Posts: 3975
Joined: Fri Jul 06, 2007 9:16 am

Re: Neutral monster

Post by CaptainToenail »

This would be so cool, you could have soldiers vs aliens vs players etc.
skadoomer
Posts: 1026
Joined: Fri Sep 05, 2003 12:49 pm

Re: Neutral monster

Post by skadoomer »

MartinHowe wrote:BLACKCAT - 15898
And i thought some of my D&D style decorate code was long. Because this is so situational (basted on the cats logic) i guess this is one of those things that needs doomscript. When i think of neutral, i think of either A) a monster that attacks everything (like the friendly flag except it targets the player as well) or B) a monster that does nothing until provoked, which is basically what a_wonder does. Anything else is pretty much situational coding.
User avatar
DBThanatos
Posts: 3101
Joined: Fri Apr 14, 2006 3:17 pm
Location: in "the darkness that lurks in our mind"
Contact:

Re: Neutral monster

Post by DBThanatos »

skadoomer wrote:B) a monster that does nothing until provoked, which is basically what a_wonder does.
Well, yes, but that doesnt really make it neutral. It prevents the monster to attack player, however is still considered hostile and your friendlies will attack it. That's why I suggested this.
skadoomer
Posts: 1026
Joined: Fri Sep 05, 2003 12:49 pm

Re: Neutral monster

Post by skadoomer »

so your looking for something more closely related to option A them?
MDenham
Posts: 161
Joined: Sun Oct 14, 2007 2:23 am

Re: Neutral monster

Post by MDenham »

skadoomer wrote:so your looking for something more closely related to option A them?
No, basically B with "friendlies don't inherently want to kill it" without openly making it friendly.
User avatar
DBThanatos
Posts: 3101
Joined: Fri Apr 14, 2006 3:17 pm
Location: in "the darkness that lurks in our mind"
Contact:

Re: Neutral monster

Post by DBThanatos »

Sorry for the bump. I was wondering if there is any chance for this? I guess it could be useful (plus the fact I need it) but what do I know? :P
User avatar
DBThanatos
Posts: 3101
Joined: Fri Apr 14, 2006 3:17 pm
Location: in "the darkness that lurks in our mind"
Contact:

Re: Neutral monster

Post by DBThanatos »

So, i had to loose my faith. Can I assume it'll be possible in doomScript?
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49056
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: Neutral monster

Post by Graf Zahl »

If you manage to write the appropriate target acquiring code, yes, otherwise no.
Post Reply

Return to “Closed Feature Suggestions [GZDoom]”