SP Tutorial Module System Flaming Skulls

Users who are viewing this thread

Keedo420

Knight at Arms
OK, all of this talk about grenades got me thinking.... In my mod, I have a magic item that is based off of the Firestaff from Mirathei's Magic Mod: Curtain Of Fire. Basically what it does is for a stream of fire that causes a grenade-like explosion when it hits the ground. I also added Mirathei's Fire Arrows to my mod, but was never entirely happy with them because the fire moved slower than the arrows. I ALSO have, for my undead, throwing skulls! That's right....my undead throw skulls at you!!!  :twisted: I always thought it would be cool if they exploded too... So all of this talk about grenades made me realize I could make it work. So basically what I have done, is combined the Fire Arrows code with the Firestaff code and put them into my throwing skulls. So now I have Flaming Exploding Skulls!! :twisted: :twisted: :twisted: I was able to adjust the shot speed to be relatively the same speed that the fire moves at. So it basically works. The player throws the skull (I haven't tested giving them to troops yet), the skull/flame move at basically the same level and more or less in the same direction depending on your throwing proficiency (it's not perfect, but much more accurate than the Firestaff was), and the explosion occurs as it should when the flame hits the ground (but not buildings or other scene props) and damages all in the area of the explosion. There's only two minor issues:

1) Not a big deal, but if the flame does not hit the ground, it continues on in a straight line past the range of the thrown skull.
2) When the flame from the skulls hits the ground and causes the explosion, the resulting big flame and smoke effects often times will continue moving in the direction the skulls were thrown. So for example, if I throw them towards a hill, I will see the explosion on my side of the hill, but the fire/smoke will occasionally be seen flying out the other side of the hill and continuing until the game makes them disappear.

Here is the code I am using.

In module_parties:
Code:
  ("fire_arrows"                  ,"You shouldn't be seeing me",    pf_disabled|pf_is_static, no_menu, pt_none, fac_commoners,0,ai_bhvr_hold,0,(0., 0),[(trp_looter,15,0)]),
  ("x_coordinate"                  ,"You shouldn't be seeing me",    pf_disabled|pf_is_static, no_menu, pt_none, fac_commoners,0,ai_bhvr_hold,0,(0., 0),[(trp_looter,15,0)]),
  ("y_coordinate"                  ,"You shouldn't be seeing me",    pf_disabled|pf_is_static, no_menu, pt_none, fac_commoners,0,ai_bhvr_hold,0,(0., 0),[(trp_looter,15,0)]),
  ("z_coordinate"                  ,"You shouldn't be seeing me",    pf_disabled|pf_is_static, no_menu, pt_none, fac_commoners,0,ai_bhvr_hold,0,(0., 0),[(trp_looter,15,0)]),
  ("x_velocity"                  ,"You shouldn't be seeing me",    pf_disabled|pf_is_static, no_menu, pt_none, fac_commoners,0,ai_bhvr_hold,0,(0., 0),[(trp_looter,15,0)]),
  ("y_velocity"                  ,"You shouldn't be seeing me",    pf_disabled|pf_is_static, no_menu, pt_none, fac_commoners,0,ai_bhvr_hold,0,(0., 0),[(trp_looter,15,0)]),
  ("z_velocity"                  ,"You shouldn't be seeing me",    pf_disabled|pf_is_static, no_menu, pt_none, fac_commoners,0,ai_bhvr_hold,0,(0., 0),[(trp_looter,15,0)]),

In module_items:
Code:
["exploding_skulls", "Exploding Skulls", [("skeleton_head_throw",0)], itp_type_thrown |itp_primary|itp_bonus_against_shield,itcf_throw_stone, 230 , weight(1.5)|difficulty(0)|spd_rtng(97) | shoot_speed(60) | thrust_damage(30 ,pierce)|max_ammo(8)|accuracy(99),imodbit_large_bag,
 [(ti_on_weapon_attack, [
	  (try_for_range,reg5,1,500),
        (assign,":chosen",-1),(assign,":mindist",99999),
        (try_for_agents,":agent"),
           (agent_get_position,pos2,":agent"),
           (get_distance_between_positions,":dist",pos1,pos2),
           (lt,":dist",":mindist"),
           (assign,":mindist",":dist"),
           (assign,":chosen",":agent"),
        (end_try),
        (gt,":chosen",-1),
        (agent_get_look_position,pos1,":chosen"),
        (position_move_z,pos1,120),
        (position_get_x,":x",pos1),
        (position_get_y,":y",pos1),
        (position_get_z,":z",pos1),
        (party_set_slot,"p_x_coordinate",":chosen",":x"),
        (party_set_slot,"p_y_coordinate",":chosen",":y"),
        (party_set_slot,"p_z_coordinate",":chosen",":z"),
        (position_move_y,pos1,110),
        (position_get_x,":xnew",pos1),
        (position_get_y,":ynew",pos1),
        (position_get_z,":znew",pos1),
        (val_sub,":xnew",":x"),
        (val_sub,":ynew",":y"),
        (val_sub,":znew",":z"),
        (party_set_slot,"p_x_velocity",":chosen",":xnew"),
        (party_set_slot,"p_y_velocity",":chosen",":ynew"),
        (party_set_slot,"p_z_velocity",":chosen",":znew"),
        (party_set_slot,"p_fire_arrows",":chosen",1),
		(play_sound,"snd_pistol_shot"),
        (assign,reg5,1000),
      (end_try),
	 ],)]],

And here is the triggers for the various mission templates:
Code:
      (ti_before_mission_start, 0, 0, [], [
(try_for_range,":slot",0,500),
    (party_set_slot,"p_fire_arrows",":slot",-1),
(end_try),]),

      (0.005, 0, 0, [],[
(try_for_agents,":agent"),                                                 
    (party_get_slot,":fire","p_fire_arrows",":agent"),
    (ge,":fire",0),
    (party_get_slot,":x","p_x_coordinate",":agent"),
    (party_get_slot,":y","p_y_coordinate",":agent"),
    (party_get_slot,":z","p_z_coordinate",":agent"),
    (party_get_slot,":xvel","p_x_velocity",":agent"),
    (party_get_slot,":yvel","p_y_velocity",":agent"),
    (party_get_slot,":zvel","p_z_velocity",":agent"),
    (val_add,":x",":xvel"),
    (val_add,":y",":yvel"),
    (val_add,":z",":zvel"),
    (position_set_x,pos1,":x"),
    (position_set_y,pos1,":y"),
    (position_set_z,pos1,":z"),
    (particle_system_burst, "psys_torch_fire", pos1, 15),
    (position_set_z_to_ground_level,pos1),
    (position_get_z,":zground",pos1),
    (try_begin),
       (le,":z",":zground"),
        (get_player_agent_no,":player_no"),
        (particle_system_burst, "psys_massive_fire", pos1, 15),
        (particle_system_burst, "psys_war_smoke_tall", pos1, 15),
        (try_for_agents,":agent"),
	      (neq,":agent",":player_no"),
	      (neg|agent_is_ally,":agent"),
		  (agent_is_alive,":agent"),
          (agent_get_look_position, pos2, ":agent"),
          (get_distance_between_positions,":dist",pos1,pos2),
          (lt,":dist",300),
          (agent_deliver_damage_to_agent,":player_no",":agent"),
        (end_try),
        (scene_prop_get_instance,":instance", "spr_explosion", 0),
        (position_copy_origin,pos2,pos1),
        (prop_instance_set_position,":instance",pos2),
        (position_move_z,pos2,1000),
        (prop_instance_animate_to_position,":instance",pos2,200),
    (else_try),
       (party_set_slot,"p_x_coordinate",":agent",":x"),
       (party_set_slot,"p_y_coordinate",":agent",":y"),
       (party_set_slot,"p_z_coordinate",":agent",":z"),
       (val_sub,":zvel",1),
       (party_set_slot,"p_z_velocity",":agent",":zvel"),
    (end_try),
(end_try),]),

And here are some screenshots of the skulls in action....

The dot at the bottom of the targetting reticule is the thrown skull just before it hit the ground.


And here is the explosion just after it hit near a mounted troop. You can see it is damaging both the rider and horse repeatedly. I chose this method instead of the instant kill method created by the agent_set_hit_points operation.


And you can see here, that in many cases, the flame and smoke persist....as does the damage if any troop get near the area of affect.... :twisted: This was unintentional, but I like it. The troop will continue to take damage until they leave the area of affect or die.


Now here is an example of the flame passing through a hill....First the explosion on my side....


Then it passes through and creates another explosion on the hill behind it.....


And continues travelling through that hill as well.....


Now in the cases where it passes the hill, the first explosion fades away unlike the previous examples where the flame persists. I would like to keep the persistant flame/damage effect, but I would like to prevent the flame from passing through hills. If any good coders can figure out how to fix that, I would greatly appreciate it. I did not create any of this code. I only modified it.
 
1) Not a big deal, but if the flame does not hit the ground, it continues on in a straight line past the range of the thrown skull.

you mean like, you want it to fall with the same rate that the skulls do?
 
bjorne. said:
1) Not a big deal, but if the flame does not hit the ground, it continues on in a straight line past the range of the thrown skull.

you mean like, you want it to fall with the same rate that the skulls do?
I would like the flame to not continue past the point that the skull falls/explosion occurs. Now if it were also possible to make the flame follow the exact path as the skull (i.e. in an arc so it looks like the skull is actually on fire) that would be an added bonus, but I don't think that is possible.
 
Yes it is possible. Only that you cannot base it like this then. I think. Cause now you got a second projectile. You need to get the only one projectile.

Or. I know what you could do. You could replace your skull with a invisible mesh. Then make a particle system with one particle. Were this one particle is a Skull Mesh. And then you place this particle system on the invisible mesh. And put a fire particle system on the mesh as well and voila. At least I think it's a good idea. But. Still. The exploding fire stream is still there. So you need to get rid of that actually. And base the explosion on something else. Like the invisible mesh.
 
Well, all I really need to figure out to make this work the way I want, is how to get the fire that follows the skull to end at a certain distance. So if I could figure out the range of the thrown weapon, the code could no doubt be modified to stop the fire_arrows party (which is the fire effect that "follows" the skull) when it exceeds that range. But there is nothing about the weapon entry that indicates range. I think this is the part I would need to modify to get it to stop at a certain distance, but I am not sure:
        (assign,":chosen",-1),(assign,":mindist",99999),
        (try_for_agents,":agent"),
          (agent_get_position,pos2,":agent"),
          (get_distance_between_positions,":dist",pos1,pos2),
          (lt,":dist",":mindist"),
          (assign,":mindist",":dist"),
          (assign,":chosen",":agent"),
        (end_try),

I'm going to play around with it later to test it out, but was hoping someone else might come up with an answer sooner than me. :razz:
 
Instead of using long-lived particles that shoot out at a fixed speed, you could try having an emitter emit short-lived particles, and move the emitter directly to follow the trajectory of the skull.

EDIT if you're just trying to limit the range of the particles to a hard ceiling, you should be able to just reduce the lifetime of the particles emitted, much simpler problem there.
 
Phew. That talk about emitters made me nervous. I have not messed around much with particle systems. My one experiment with particles crashed the game. :oops: I'll try your ideas reg5 and/or the particle life.
 
Wait wait I just read it PROPERLY this time...

Add the red line to disable the projectile after explosion. That's all, easy as pie.

EDIT2: Oh, **** me, he re-used the ":agent" var. need another line grrr.

      (ti_before_mission_start, 0, 0, [], [
(try_for_range,":slot",0,500),
    (party_set_slot,"p_fire_arrows",":slot",-1),
(end_try),]),
      (0.005, 0, 0, [],[
(try_for_agents,":agent"),                                               
    (party_get_slot,":fire","p_fire_arrows",":agent"),
    (ge,":fire",0),
(assign, ":agent_slot",":agent"),
    (party_get_slot,":mad:","p_x_coordinate",":agent"),
    (party_get_slot,":y","p_y_coordinate",":agent"),
    (party_get_slot,":z","p_z_coordinate",":agent"),
    (party_get_slot,":mad:vel","p_x_velocity",":agent"),
    (party_get_slot,":yvel","p_y_velocity",":agent"),
    (party_get_slot,":zvel","p_z_velocity",":agent"),
    (val_add,":mad:",":mad:vel"),
    (val_add,":y",":yvel"),
    (val_add,":z",":zvel"),
    (position_set_x,pos1,":mad:"),
    (position_set_y,pos1,":y"),
    (position_set_z,pos1,":z"),
    (particle_system_burst, "psys_torch_fire", pos1, 15),
    (position_set_z_to_ground_level,pos1),
    (position_get_z,":zground",pos1),
    (try_begin),
      (le,":z",":zground"),
        (get_player_agent_no,":player_no"),
        (particle_system_burst, "psys_massive_fire", pos1, 15),
        (particle_system_burst, "psys_war_smoke_tall", pos1, 15),
        (try_for_agents,":agent"),
        (neq,":agent",":player_no"),
        (neg|agent_is_ally,":agent"),
        (agent_is_alive,":agent"),
          (agent_get_look_position, pos2, ":agent"),
          (get_distance_between_positions,":dist",pos1,pos2),
          (lt,":dist",300),
          (agent_deliver_damage_to_agent,":player_no",":agent"),
        (end_try),
        (scene_prop_get_instance,":instance", "spr_explosion", 0),
        (position_copy_origin,pos2,pos1),
        (prop_instance_set_position,":instance",pos2),
        (position_move_z,pos2,1000),
        (prop_instance_animate_to_position,":instance",pos2,200),
    (party_set_slot,"p_fire_arrows",":agent_slot",-1),
  (else_try),
      (party_set_slot,"p_x_coordinate",":agent",":mad:"),
      (party_set_slot,"p_y_coordinate",":agent",":y"),
      (party_set_slot,"p_z_coordinate",":agent",":z"),
      (val_sub,":zvel",1),
      (party_set_slot,"p_z_velocity",":agent",":zvel"),
    (end_try),
(end_try),]),
 
aah. So basicly the flames are the projectile. So it isn't just flames atached to a projectile?
 
Well, this is what he had in there before I added in the explosion part:

    (try_begin),
      (le,":z",":zground"),
      (particle_system_burst,"psys_torch_fire",pos1, 1000),
      (party_set_slot,"p_fire_arrows",":agent",-1),
    (else_try),

So apparently I removed the red line when I replaced the particle burst with the explosion.

aah. So basicly the flames are the projectile. So it isn't just flames atached to a projectile?
Right. Well, the skull itself is still a projectile. It will still do damage if it hits the enemy, but the flame basically just follows it and causes an explosion if the flame touches the ground.
 
Keedo420 said:
aah. So basicly the flames are the projectile. So it isn't just flames atached to a projectile?
Right. Well, the skull itself is still a projectile. It will still do damage if it hits the enemy, but the flame basically just follows it and causes an explosion if the flame touches the ground.

Basically the skull will hit the target, while the flame will continue on and explode just behind it.
 
Right. The explosion will happen whether the skull hits the target or not, as long as it touches the ground. If you aim at an angle where there is no ground in the targeting reticule, there will be no explosion even if the skull hits a target. I just got an idea though..... I'll be back in a while. :wink:
 
Won't it look kinda weird to have people marching around with skulls stuck to their shields?
 
I hadn't thought much about that, but I haven't noticed it happen yet. Only a little bit weirder than having stones stuck to your shield I guess. But the skulls will have a very low max ammo (currently set to 6).... I mean you really can't carry more than....6 Heads In A Dufflebag anyway. :lol:
 
I think I made them piercing because of the explosion, but I guess changing it to blunt might be a good idea.

Also, I have somewhat solved the problem of the flame going past the range of the skulls. I set up a distance check between the player and the flame, so when it gets a certain distance away, it causes the explosion and apparently stops. HOWEVER.... :sad: While the Bonfire created by the explosion persists like it does when striking the ground, it moves away from me when I approach it. This doesn't happen when the explosion occurs on the ground.

Here's my current code:
Code:
      (0.005, 0, 0, [],[
(try_for_agents,":agent"),                                                 
    (party_get_slot,":fire","p_fire_arrows",":agent"),
    (ge,":fire",0),
    (party_get_slot,":x","p_x_coordinate",":agent"),
    (party_get_slot,":y","p_y_coordinate",":agent"),
    (party_get_slot,":z","p_z_coordinate",":agent"),
    (party_get_slot,":xvel","p_x_velocity",":agent"),
    (party_get_slot,":yvel","p_y_velocity",":agent"),
    (party_get_slot,":zvel","p_z_velocity",":agent"),
    (val_add,":x",":xvel"),
    (val_add,":y",":yvel"),
    (val_add,":z",":zvel"),
    (position_set_x,pos1,":x"),
    (position_set_y,pos1,":y"),
    (position_set_z,pos1,":z"),
    (particle_system_burst, "psys_torch_fire", pos1, 15),
    (position_set_z_to_ground_level,pos1),
    (position_get_z,":zground",pos1),
	(get_player_agent_no,":player_no"),
    (agent_get_look_position,pos3,":player_no"),
    (get_distance_between_positions,":skull_dist",pos1,pos3),
    (try_begin),
       (le,":z",":zground"),
        (particle_system_burst, "psys_massive_fire", pos1, 15),
        (particle_system_burst, "psys_war_smoke_tall", pos1, 15),
        (try_for_agents,":agent"),
	      (neq,":agent",":player_no"),
	      (neg|agent_is_ally,":agent"),
		  (agent_is_alive,":agent"),
          (agent_get_look_position, pos2, ":agent"),
          (get_distance_between_positions,":dist",pos1,pos2),
          (lt,":dist",300),
          (agent_deliver_damage_to_agent,":player_no",":agent"),
        (end_try),
        (scene_prop_get_instance,":instance", "spr_explosion", 0),
        (position_copy_origin,pos2,pos1),
        (prop_instance_set_position,":instance",pos2),
        (position_move_z,pos2,1000),
        (prop_instance_animate_to_position,":instance",pos2,200),
		(party_set_slot,"p_fire_arrows",":agent",-1),
    (else_try),
		(ge,":skull_dist", 2000),
        (particle_system_burst, "psys_massive_fire", pos1, 15),
        (particle_system_burst, "psys_war_smoke_tall", pos1, 15),
        (try_for_agents,":agent"),
	      (neq,":agent",":player_no"),
	      (neg|agent_is_ally,":agent"),
		  (agent_is_alive,":agent"),
          (agent_get_look_position, pos2, ":agent"),
          (get_distance_between_positions,":dist",pos1,pos2),
          (lt,":dist",300),
          (agent_deliver_damage_to_agent,":player_no",":agent"),
        (end_try),
        (scene_prop_get_instance,":instance", "spr_explosion", 0),
        (position_copy_origin,pos2,pos1),
        (prop_instance_set_position,":instance",pos2),
        (position_move_z,pos2,1000),
        (prop_instance_animate_to_position,":instance",pos2,200),
		(party_set_slot,"p_fire_arrows",":agent",-1),
	(else_try),
       (party_set_slot,"p_x_coordinate",":agent",":x"),
       (party_set_slot,"p_y_coordinate",":agent",":y"),
       (party_set_slot,"p_z_coordinate",":agent",":z"),
       (val_sub,":zvel",1),
       (party_set_slot,"p_z_velocity",":agent",":zvel"),
    (end_try),
(end_try),]),

Any ideas on this new problem?
 
I think that's because of pos3, because you're bound to it, and so it continues to calculate distance as long as the system lives. But I'm not great at python and I've never played around with particles, so I might be wrong.
I wondered if there is any way to make a stone, combined with fire particle system and that's why this thread attracted my attention.
 
You didn't do my fix. Check my post again.

Also, wouldn't it be much easier to make it explode either if it's "close enough" to an agent, OR if it hits the ground??
 
Back
Top Bottom