One Minute Game Review by The Happy Friar:
Also on Rumble:

idTech 4 (aka Doom 3 tech) Discord Server!

Main Menu

How to compile Doom 3 source

Started by Mr A, August 12, 2014, 09:49:18 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Mr A

I tried this but it was unsuccessful.  Still won't spawn decals. 

void monster_zombie_security_pistol::state_Killed() {

sys.setSpawnArg( "fx", "fx/bloodpool" );
sys.setSpawnArg( "origin", getOrigin() );
sys.setSpawnArg( "start", "1" );
sys.spawn( "func_fx" );

animState( ANIMCHANNEL_TORSO, "Torso_Death", 0 );
animState( ANIMCHANNEL_LEGS, "Legs_Death", 0 );

waitAction( "dead" );


I don't think FX is a system function. Entity should be spawning FX afaik.

Mr A



I just tested this functionality using the punch event in the fists weapon and it works fine and puts a huge bloody decal on the floor. Obviously you don't want it being at the players origin so just remove $player1.

sys.print( "PunchLeft\n" );
sys.setSpawnArg( "fx", "fx/arx_blood_pool" );
sys.setSpawnArg( "origin", $player1.getOrigin() );
sys.setSpawnArg( "start", "1" );
sys.spawn( "func_fx" );

This is the fx def I have set up for this test:

fx fx/arx_blood_pool
name "decal1"
offset 0, 0, 0
delay 0.0
duration 100
size 200
restart 1
decal "textures/arx/decals/blood_smear1"


Use sys.print in your script to make sure your code is being called.
Type g_showentityinfo 1 at the console and make sure a func_fx is being spawned in the world where you think it should.

Edit: You don't want "restart 1" either. This was just for testing.


Mr A

Okay well I did what you recommended Solarspace.  My script works fine and the fx is working, sort of.  When I showed entity info, my fx was noted, but the box was just floating there where the monster had died.  It's really bizarre!



Glad you got it working! - you did now get a decal on the floor???

If you set "restart 0" in the FX definition then the game-code will remove the func_fx entity from the world after all of its effects have completed. You should probably only see a bounding box (with g_showentityinfo) for as long as your decal is visible in this case.


Edit: I wonder if we should re-name this post / thread to something more appropriate as someone looking for info on compiling the source is not going to find much related to that in here. Thanks.

Mr A

No the decal isn't on the floor haha, but there's a box appeared to show the effect is happening. I even tried lowering the offset so it was closer to the floor, but that didn't help.  This is really weird.  Doom hates me =c

I'm going to try with a custom decal, 
Custom decal failed... I have no idea why this won't work =/

Yeah a rename probably would be a good idea haha.
I still want to know how to compile the source code though. 

Mr A

Right, well it works when I use "sys.setSpawnArg( "origin", $player1.getOrigin() );",
but not when I don't.

The decal will also spawn when I use other origins, jsut not when it's left blank. 

How do I set the origin as the monster that's just died?




sys.setSpawnArg( "origin", self.getOrigin() );

From within the IA's script. Although getOrigin should equate to the same thing within the context of the AI's own script object ???

Good luck!

Mr A

It does the same as before, with the fx just spawning mid air and not painting the decal. 

A took a screenshot.



Finally had time to test this out properly and my findings agree with yours. The behaviour is different when the script is run from the state_killed event.

The answer to why this is happening and the solution took quite a bit of fiddling to find out. However, this is quite a good example of why it is often easier to do things like this from code within the SDK rather than scripts. However, at the same time, it is also a good example that where there is a will there is very frequently a way with scripts if that is how you want to work.

There are two reasons why the script does not work from within the state_killed event:


The decal functionality of the FX requires that the FX origin is about 4 to 8 units from the floor. As we can see, the origin of the FX is further from the floor than this when spawned using the AI origin in this event.


If the AI has a ragdoll, then because of the sequence of events in the SDK and the SDK setting the script "state_killed" and the transition into ragdoll state, then running "think" for the AI which updates the script... This means that from script in the state_killed event you are not getting the origin point of the MD5 model. You are getting the origin point based on the articulated figures "body" containing the "origin" joint in the articulated figure file. Look below and you can see the origin z offset. I have proved this is the case by manipulating the offset to crazy values and the resultant getOrigin() changes in accordance:

Example (

body "waist" {
joint "origin"
mod orientation
model box( ( -5.5, -7.5, -6 ), ( 5.5, 7.5, 6 ) )
origin ( 0, 0, 44 )

As promised here is a script that works around the problem. It seems to work pretty well, but has not been exhaustivly tested:

A working solution to your problem is here:

sys.print( "Started: monster_zombie_base::state_Killed()\n" );

// ***************************************************
// ***************************************************
// Variables
entity myFX;
vector newFXOrigin;
float traceDistance;
vector beginTracePoint;
vector endTracePoint;
float traceFrac;

// Set values
traceDistance = 64.0; // Only trace this far to be realistic

// At this point the AI origin will be several units up off the floor
beginTracePoint = self.getWorldOrigin();

endTracePoint = beginTracePoint;
endTracePoint_z = endTracePoint_z - traceDistance;

// Trace down by traceDistance units to try and find something solid under us
traceFrac = sys.trace( beginTracePoint, endTracePoint, '0 0 0', '0 0 0', MASK_SOLID|CONTENTS_RENDERMODEL, self );

// Using the trace fraction from the trace we work out how many units to move the FX down
newFXOrigin = beginTracePoint;
newFXOrigin_z = newFXOrigin_z - ( traceFrac * traceDistance );

// Here we drop the decal using the spawned FX entity
sys.setSpawnArg( "fx", "fx/arx_blood_pool" );
sys.setSpawnArg( "start", "0" );
sys.setSpawnArg( "triggered", "1" );
myFX = sys.spawn( "func_fx" );
myFX.setOrigin( newFXOrigin );

sys.trigger( myFX );

// ***************************************************
// ***************************************************


Mr A

It's working pretty perfectly!
Now when I rocket enemies it leaves loads of blood =D