(03-18-2012, 06:31 AM)Damascus Wrote: I studied the section you were talking about, and saw that there are options for creating particle effects, sounds, and thrown objects when something hits hard enough. I probably won't be able to deal damage with it, but can probably achieve the explosion effect.
However, after thinking hard about it, I think it might make the game far too frustrating if the player throws it against the wrong object and loses the item, no longer able to advance in the game. But then, if I make it only explode when thrown against the right object, I risk making it look unrealistic. What to do... what to do...
One solution would be to provide an infinite supply of the explosive items (e.g fill a chest with 3 or 4 of them, and when one is destroyed spawn a new one with createEntityAtArea). When the puzzle is solved you can just disable the respawn. I Might make an attempt to come up with an example map showing my approach later today.
(03-18-2012, 06:31 AM)Damascus Wrote: I studied the section you were talking about, and saw that there are options for creating particle effects, sounds, and thrown objects when something hits hard enough. I probably won't be able to deal damage with it, but can probably achieve the explosion effect.
However, after thinking hard about it, I think it might make the game far too frustrating if the player throws it against the wrong object and loses the item, no longer able to advance in the game. But then, if I make it only explode when thrown against the right object, I risk making it look unrealistic. What to do... what to do...
One solution would be to provide an infinite supply of the explosive items (e.g fill a chest with 3 or 4 of them, and when one is destroyed spawn a new one with createEntityAtArea). When the puzzle is solved you can just disable the respawn. I Might make an attempt to come up with an example map showing my approach later today.
You sir are a gentleman and a scholar! This is exactly what I was going for! I don't quite understand how you got all the boxes to fly away from it, based on your earlier post, but I'm going to work hard to get this to work in my level!
By the way, what sound and PS did you use? I can't find anything that comes close.
Firstly, i forgot to include the SDIV entities, so re-download the zip file if you downloaded the old one and all the stuff should be there now .
I created a custom particle effect called "explosion.ps" - based off one of the gaurdian effects initially. The sound is one of the break sound effects. An overview of how the system works is as follows:
Firstly, I added two routines for handling math functions later, called "approx" and "sqrt", fairly self explanatory as to what these do, and these are taken from my math library.
I then included my string list library (with a few functions stripped out & optimised for viewing without the collapsing editor regions). This library simply maintains a list data structure of strings without leaking variables - this lets me add and remove elements to and from a list which is very useful later on. Both these libraries are self contained and the full versions can be obtained in the wiki topic in the development forum.
I've tried to build a self contained system for explosions, but note there are some limitations which i will come to later on. Firstly, here is a more detailed description of how the system works
overview
Spoiler below!
I attach an explosion radius object to the grenade object. I then add every object that enters this radius to a list, removing it if it leaves the radius. At *some point* a grid of boxes is generated around the grenade which will be talked about later.
When the grenade detonates I look at every object which is in the list of objects in the radius. I then calculate the distance of that object to the centre of the explosion, as well as the relative position of the two objects. I then apply a force based of the inverse square of the distance along the unit vector specified by the relative position of the two objects. I also apply damage using the inverse square of the distance too, but most props don't use health so this doesn't really do much.
constants
Spoiler below!
EXPRADIUS = "_EXPRADIUS"
This is just a string appended onto the end of the explosive object's name to get the name of the attachment used for collision detection.
CCMA_NAME = "CCMA_"
This is the first part of the name for the objects attached which will allow us to determine the relative position of objects.
SDIV = "sdiv"
This is the first part of file name of the SDIV entities.
TIMESTEP = 1.0f / 60.0f
This actually isn't used anymore and i forgot to remove it. Sorry!
MINPRECISION = 0.0625f
The smallest SDIV object to be used.
PRECISION = 4
The level of precision to use. Higher = better but slower. Must be a power of 2 (I.e 1,2,4,8,16,32...)
Starts tracking an object as an explosive item. asItemName: The name of the item you want to track as a grenade (when it breaks, boom!). asFile: The name of the file which will specify the explosion. In this example i just have a sphere of radius 2. afRadius: The radius of the explosion (must be at least as big as the radius of the body in the above entity). afForce: The force that should be applied at the centre of the explosion (max force). Negative values are supported. The force is diminished the further an object is away from the explosion. afDamage: The damage that should be applied at the centre of the explosion, same as above. returns true if the explosion was initialized correctly for this object
Internally, this routine just sets up a load of local variables, and makes the radius into the nearest power of two. It also adds the necessary callbacks for when an object breaks.
explosions_InitExplosiveItemMesh(string &in asItemName)
Call this at some point after the explosions_AddExplosiveItem and before the item breaks. This will create a mesh around the item which is used only when the item breaks. This mesh may take a while to add and might cause a lag spike, so you probably want this while the map loads so it isn't noticable. asItemName: The name of the item which is ALREADY being tracked as a grenade
Internally, this iterates over over all the x,y,z coordinates -radius to +radius in steps of "radius/PRECISION" and attaches the SDIV entities with the name "CCMA_" at each coordinate. The step size and starting id of each entity is tracked for later
How the system tracks objects to effect by explosion impulses
Spoiler below!
explosions_RadiusCollideCallback
When an object enters/exits the radius attachment of the grenade, this callback is triggered. That object is then added/removed from a unique list for that grenade.
How the system applies impulses to objects
Spoiler below!
explosions_Determinelocations
This is called after the object breaks. It operates in a similar manner to the InitExplosiveItemMesh function. This will go over every cell for this grenade for every object in range (a lot of iterations!). It then will determine for each object the cells which are inside it. The minimum distance is stored as well as the sum of the positions of each of the cells (which is later averaged to determine (roughly) the centre of the object in the radius, relative to the centre of the explosion).
explosions_CallbackOnBreak
This is the callback when the object breaks. It obtains from the string list all the entities in range of this explosion (as determine by the range/radius mesh object). It then puts out a call to explosions_Determinelocations - in order to get, for each object, a position sum and a distance from the explosion origin.
The position sum is averaged to determine a rough origin for each object, and the force is then mitigated by "1/(distance * distance)", and applied in the normalised vector specified by averaged position. If an object is directly in the centre of the explosion, a little hack is included to give it a purely vertical impulse - this may happen if the object is small or with a low precision value. Health is modified in a similar way.
Finally, a call to OnGrenadeExplosion is triggered after all the above takes place so that you can include gameplay code when the grenade explodes without overwriting the callbacks added by this system.
The code in the OnStart(), LeverCallback and OnGrenadeExplode() is the specific code used for this demo (allowing the lever to spawn a new grenade object if the old one has detonated).
However, there are still some limitations:
Don't set the Precision variable any higher, the game WILL lag significantly if this variable is too high.
Items which will be effected must begin with "item_", and any explosive object must NOT be effected by explosions (i.e don't let it begin with "item_"). The game will crash if this does not occur.
Creating too many grenades will crash the game, as the game will randomly crash after too many calls to AddAttachedPropToProp.
A fix was included due to glitches in AddAttachedPropToProp - if this ever gets fixed in a future patch this code will need to be edited (instead of the last arguments being x,y,0,z,90,z use x,y,z,0,0,0)
When getting this to work in your level, you should be able to copy any paste everything but the OnStart and cbLeverPull code.
(This post was last modified: 03-18-2012, 09:53 PM by Apjjm.)
THANK YOU SO MUCH! Any chance you can make one with the small_stone01.dae mesh and body? I'm trying to do it myself but it keeps showing up as just a regular bottle. I'll credit the hell out of you when I use it in my custom story!
So for blowing open the door I basically want to copy and paste all this into my script (except the exceptions you mentioned) and give the door "item_" to begin it's name? And just to make sure it dies, I can also make a script area that instakills the door on impact.
A note about "bodies" which I forgot to mention - you need to ensure the body cannot rotate (I do this with an insane damping value and angular speed limit) otherwise the explosion will push things in the wrong direction. With regards to your second question, yes that would work, but you can also give the explosion a damage value (see the parameter afDamage in the creation code). I believe doors do actually use health to track how broken by a monster they are so a script area might not be necessary.
I'm not sure exactly what in the code to edit, but I evidently need to deal 100 damage to destroy the door (and the boards blocking it). If I don't do this, though, the script area is working pretty nicely. It just also goes off when you carry the rock up to the door, too.
EDIT: Also, not entirely sure why, but I had this issue in another thread, too. I put in the new grenade you provided and am still getting a bottle in-game. someone suggested I delete my map_cache, but I don't have any.
explosions_AddExplosiveItem("grenade1_1","grenade1_explosion.ent",2,10000,10);
// ^ Has damage 10. Change it to give it 110 damage at the centre:
explosions_AddExplosiveItem("grenade1_1","grenade1_explosion.ent",2,10000,110);
---
Are the grenade objects placed through the level editor or created inside the script? If it's inside the script make sure you are using the correct names (the new entity was called grenade01_NEW.ent so you might have accidentally missed a line or something), if it's the level editor (after re-starting it) verify that the changes appear in the level editor (if they don't, the fault isn't with the map cache). Also make sure you have "forceCacheLoadingAndSkipSaving" set to false in the main_settings.cfg in your saves folder.
(This post was last modified: 03-19-2012, 01:40 AM by Apjjm.)
I'm placing it in the level editor. The change does appear in the editor, and shows up as a small rock. If I replace the original grenade .ent with the new one, it still appears as a bottle in game. If I instead choose to just target the new "grenade1_NEW.ent", then it doesn't show up in game at all. Still, both of them appear correctly when viewed through the level editor.