Another, maybe more fast, way would be using a "FOR" to cycle through all ents, using vec_dist and c_trace ( c_trace to avoid applying "explo - damage" behind / through walls ).
Note: c_scan will only return the nearest entity ( YOU ) found. Use a FOR instead ( +vec_dist ), or entities EVENT_SCAN to react to more than one at once. If your scanmode contains SCAN_ENTS, then only ents with ENABLE_SCAN flag set, will be found / event - triggered. Guess u know already, just wanted to remind.
my.emask |= (ENABLE_SCAN | WHATEVER...); // now c_scan + SCAN_ENTS detects / triggers me
C_SCAN probs, another thread: Replace c_scan with FOR and vec_distHeres a simple example of a "selfmade c_scan / explosion without c_scan" ( not tested but iam pretty sure it'll compile n run ):
ENTITY* myplayer;
#define health skill100
#define can_explode skill99
#define do_explode skill98
#define removeable skill97
void rayps_exploscan (ENTITY* _ent){
if (!_ent) return; // entity doesnt exist? stop!
if (me) my.removeable = 0; // when 1, explosion done, "FOR" cycled through all ents
var _explorange = 300; // range of explosion ( _ent.x + 300 )
var _stored_you = 0; // guess this is optional. avoids(?) that this code changes YOU
if (you) _stored_you = handle (you);
for (you = ent_next (NULL); you; you = ent_next (you)){
//if (!_ent) break; // wtf!?! lost _ent - entity? stop!
var _dist2ent = _explorange + 1; // distance _ent.x -> you[n].x: starts false(>range)
_dist2ent = vec_dist (_ent.x, you.x); // _dist2ent = distance between _ent and you[n]
if (you.can_explode){ // only damage some ents, with "can_explode = 1" 4ex
trace_mode = IGNORE_ME | IGNORE_PASSABLE | USE_POLYGON;
if (_dist2ent < _explorange) if (c_trace (_ent.x, your.x, trace_mode)){ // hit something?
you.health = 0; // you.can_explode=1 + in range + hit by c_trace? DIE!
you.can_explode = 0; // only a "oneshot" event
you.do_explode = 1; // when ent dies, it'll produce an explosion too
}
}
}
if (_stored_you) you = ptr_for_handle (_stored_you); // restores you - pointer (optional?)
if (me) my.removeable = 1; // me aka my, still exists? then mark as removeable now!
}
action WED_Barrel_Explo{ // very basic n simple example of an explodeable object
my.do_explode = 0; // if set to 1, we'll explode when health <= 0
my.can_explode = 1; // now the "FOR" takes care about us ( = we're explodeable now )
my.health = 100;
while (my.health){ // iam alive...
draw_text ("Barrel: Waiting 4 rayps_exploscan's in range (health>0)...", 10, 10, vector (0, 0, 255));
wait (1);
}
set (my, PASSABLE | INVISIBLE); // switch in2 ghostmode :D
if (my.do_explode) rayps_exploscan (me); // produce another explosion, this time at "my" pos
while (!my.removeable) wait (1); // while zero, my explosion (FOR) is still running
wait (1);
ptr_remove (me); // finally remove this exploded, damaged barrel
}
action myHero(){
myplayer = me;
...
while (my.health > 0){
...
if (key_space && !myplayer.removeable) rayps_exploscan (myplayer); // debug: spawn explo's around player (waits until explo done)
...
wait (1);
}
...
}
About the c_scan command values, this works normally for a simple "explosion - scan":
c_scan (my.x, my.pan, vector (360, 0, 1000),...
Should scan in a "circle" ( 360° ) cone, into the direction "my" looks to, in a range of 1000.
Great 4 debugging traces or scans ( some may not know yet ):
c_trace (...tracestuff...);
if (HIT_TARGET) draw_point3d (target.x, vector (50, 50, 255), 100, 3);
// ---------------------------------------------------------------------------------
// mhm, not sure c_scan sets HIT_TARGET, thats why i would use "result" 2 compare instead
if (c_scan (...scanstuff...)) draw_point3d (target.x, vector (50, 50, 255), 100, 3);
Displays a red point, one frame long, at "target"s - vector - position.
Greets N peace