Jump to content

Possible to prevent NPCs from using ragdoll behavior upon death? I.E. JK2 behavior?


Recommended Posts

Posted

Was wondering if its possible to prevent an NPC from using ragdoll upon being killed. Preferably it would be a scripted behavior that I could assign to any NPC, but I didn't see any that sounded like that when I perused Behaved.

  • 3 weeks later...
Posted
2 hours ago, Linken said:

Type "broadsword 0"

Possible to make this scriptable? Only want it to occur in a specific situation. Even just toggling this on/off would work, but I'm not looking for cheats

Posted
2 minutes ago, Linken said:

Are you looking for it to be global or only impact specific npcs?

In this case either would be fine, it would be during a duel and going back to what it was after the duel

Posted
11 hours ago, RebornKyle said:

In this case either would be fine, it would be during a duel and going back to what it was after the duel

Alright, I'll leave it up to you on how to implement or how to call it. So I'll write some simple tutorials. I'm going light on the details since I know you have a coding background, but let me know if you need screenshots.

1. In Q3_Interface.h, declare your new script command.

2. In Q3_Interface.cpp, add your command to the Enum2String and the Set method in the appropriate spot (would recommend making it a Boolean)

3. IF Making Global: have it change the value of the "g_broadsword" cvar to 0 (turned off) or 1 (turned on) depending if set to true or false. You can stop here. 

4. IF Making NPC Specific, declare a new NPC scriptFlag (in b_public.h). In this example I'll just call it SCF_NO_RAGDOLL, make sure its Hexadecimal value is correct. An unmodified OpenJK source code should probably be 0x100000000. 

5. To apply to an NPC, create a new function somewhere called by your script command and write something like this:

static void Q3_SetRagdoll(int entID, qboolean ragDoll)
{
	gentity_t *ent = &g_entities[entID];
	
	if ( !ent )
	{
		Quake3Game()->DebugPrint( IGameInterface::WL_WARNING, "Q3_SetRagdoll: invalid entID %d\n", entID);
		return;
	}

	if(ragDoll)
		ent->NPC->scriptFlags |= SCF_NO_RAGDOLL;
	else
		ent->NPC->scriptFlags &= ~SCF_NO_RAGDOLL;
}

6. Lastly go to the function G_RagDoll (in g_main.cpp) and add a check near the beginning of the function to verify if the NPC has this scriptFlag applied, and if they do, return qfalse.

DISCLAIMER: I wrote this code on the fly and didn't personally test.

Posted
On 12/21/2024 at 12:41 PM, Linken said:

Alright, I'll leave it up to you on how to implement or how to call it. So I'll write some simple tutorials. I'm going light on the details since I know you have a coding background, but let me know if you need screenshots.

1. In Q3_Interface.h, declare your new script command.

2. In Q3_Interface.cpp, add your command to the Enum2String and the Set method in the appropriate spot (would recommend making it a Boolean)

3. IF Making Global: have it change the value of the "g_broadsword" cvar to 0 (turned off) or 1 (turned on) depending if set to true or false. You can stop here. 

4. IF Making NPC Specific, declare a new NPC scriptFlag (in b_public.h). In this example I'll just call it SCF_NO_RAGDOLL, make sure its Hexadecimal value is correct. An unmodified OpenJK source code should probably be 0x100000000. 

5. To apply to an NPC, create a new function somewhere called by your script command and write something like this:

static void Q3_SetRagdoll(int entID, qboolean ragDoll)
{
	gentity_t *ent = &g_entities[entID];
	
	if ( !ent )
	{
		Quake3Game()->DebugPrint( IGameInterface::WL_WARNING, "Q3_SetRagdoll: invalid entID %d\n", entID);
		return;
	}

	if(ragDoll)
		ent->NPC->scriptFlags |= SCF_NO_RAGDOLL;
	else
		ent->NPC->scriptFlags &= ~SCF_NO_RAGDOLL;
}

6. Lastly go to the function G_RagDoll (in g_main.cpp) and add a check near the beginning of the function to verify if the NPC has this scriptFlag applied, and if they do, return qfalse.

DISCLAIMER: I wrote this code on the fly and didn't personally test.

Well hey I greatly appreciate this! I'll be sure to give this a go when I have some time soonish. I'll probably opt for the specific NPC one since setting it globally would probably get messy if other users prefer it differently and having to change it back afterwards could alter those preferences. Happy Holidays!

Linken likes this
Posted
On 12/21/2024 at 12:41 PM, Linken said:

4. IF Making NPC Specific, declare a new NPC scriptFlag (in b_public.h). In this example I'll just call it SCF_NO_RAGDOLL, make sure its Hexadecimal value is correct. An unmodified OpenJK source code should probably be 0x100000000. 

5. To apply to an NPC, create a new function somewhere called by your script command and write something like this:

static void Q3_SetRagdoll(int entID, qboolean ragDoll)
{
	gentity_t *ent = &g_entities[entID];
	
	if ( !ent )
	{
		Quake3Game()->DebugPrint( IGameInterface::WL_WARNING, "Q3_SetRagdoll: invalid entID %d\n", entID);
		return;
	}

	if(ragDoll)
		ent->NPC->scriptFlags |= SCF_NO_RAGDOLL;
	else
		ent->NPC->scriptFlags &= ~SCF_NO_RAGDOLL;
}

6. Lastly go to the function G_RagDoll (in g_main.cpp) and add a check near the beginning of the function to verify if the NPC has this scriptFlag applied, and if they do, return qfalse.

DISCLAIMER: I wrote this code on the fly and didn't personally test.

I managed to accomplish the global change, but just like I thought it would affect later sessions if you didn't reset it. I haven't managed to figure out the scriptflag for specific NPCs unfortunately though. Here's the relevant parts of what I wrote:

Q3_Interface:
____________________________________________________________________

ENUM2STRING(SET_NO_RAGDOLL),
-----------------------------------------------------------------
/*
============
Q3_SetNoRagdoll
  Description :
  Return type : static void
  Argument :  int entID
  Argument : qboolean ragdoll
============
*/
static void Q3_SetNoRagdoll(int entID, qboolean ragdoll)
{
gentity_t *ent = &g_entities[entID];

if (!ent)
{
Quake3Game()->DebugPrint(IGameInterface::WL_WARNING, "Q3_SetNoRagdoll: entID %d not a client\n", entID);
return;
}

if (ragdoll)
{
ent->NPC->scriptFlags |= SCF_NO_RAGDOLL;
}
else
{
ent->NPC->scriptFlags &= ~SCF_NO_RAGDOLL;
}
}
--------------------------------------------------------------------------------
case SET_NO_RAGDOLL://## %t="BOOL_TYPES" # NPCs won't ragdoll on death
if (ent->NPC == NULL)
{
DebugPrint(WL_WARNING, "GetFloat: SET_NO_RAGDOLL, %s not an NPC\n", ent->targetname);
return false;
}
*value = (ent->NPC->scriptFlags&SCF_NO_RAGDOLL);
break;



g_main:
____________________________________________________________________

//rww - game interface for the ragdoll stuff.
//Returns qtrue if the entity is now in a ragdoll state, otherwise qfalse.
//(ported from MP's CG version)

qboolean G_RagDoll(gentity_t *ent, vec3_t forcedAngles)
{
vec3_t G2Angles;
vec3_t usedOrg;
qboolean inSomething = qfalse;
int ragAnim;
//int ragVar = gi.Cvar_VariableIntegerValue("broadsword");
int ragVar = g_broadsword->integer;

if (!ragVar)
{
return qfalse;
}

if (!ent ||
!ent->inuse ||
!ent->client ||
ent->health > 0 ||
ent->client->noRagTime >= level.time ||
ent->client->noRagTime==-1 ||
(ent->s.powerups & (1 << PW_DISRUPTION)) ||
!ent->e_DieFunc ||
  ent->playerModel < 0 ||
!ent->ghoul2.size() ||
!G_RagWantsHumanoidsOnly(&ent->ghoul2[ent->playerModel])
)
{
return qfalse;
}

if (ent->NPC->scriptFlags & SCF_NO_RAGDOLL)
{
return qfalse;
}


So not sure if something I did here is off or not. Oh and of course I declared the SCF_NO_RAGDOLL in b_public.h and the SET_NO_RAGDOLL in Q3_Interface.h. I noticed that, for g_main, any level won't start if I put the last if statement I created before the previous if block

Linken likes this
Posted

The way you wrote it is not the global change, it's the NPC change. Global change would only impact the cvar.

Looking at your code I don't see any issues. What does your script look like for calling this?

Posted
2 minutes ago, Linken said:

The way you wrote it is not the global change, it's the NPC change. Global change would only impact the cvar.

Looking at your code I don't see any issues. What does your script look like for calling this?

Yes sorry I should have clarified, this is for the NPC change. I accomplished the global change, but it wasn't satisfactory for me.

And my script is called when the NPC is spawned, along with the other behaviors its spawned with, which are all base game and work fine as they did before this addition. Here's the script call.
set ( /*@SET_TYPES*/ "SET_NO_RAGDOLL", /*@BOOL_TYPES*/ "true" );

Posted
52 minutes ago, RebornKyle said:

Yes sorry I should have clarified, this is for the NPC change. I accomplished the global change, but it wasn't satisfactory for me.

And my script is called when the NPC is spawned, along with the other behaviors its spawned with, which are all base game and work fine as they did before this addition. Here's the script call.
set ( /*@SET_TYPES*/ "SET_NO_RAGDOLL", /*@BOOL_TYPES*/ "true" );

Does the global change work through the script?

Posted
9 minutes ago, Linken said:

Does the global change work through the script?

Yes, but for that it would be set as ( /*@SET_TYPES*/ "SET_NO_RAGDOLL", 0);
Since my solution for that involves directly changing the cvar for broadsword, as you suggested.

Posted

.

34 minutes ago, RebornKyle said:

Yes, but for that it would be set as ( /*@SET_TYPES*/ "SET_NO_RAGDOLL", 0);
Since my solution for that involves directly changing the cvar for broadsword, as you suggested.

Check the script command in debug mode, there might be something missing

Posted
On 12/29/2024 at 1:07 AM, Linken said:

.

Check the script command in debug mode, there might be something missing

Maybe there could be a different area to implement this? I've gotten nothing checking the script. Since ragdoll only applies to humanoid npcs, maybe there's a point in the code where that is laid out, and I can do the check there?

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
×
×
  • Create New...