c_scan ( different explo damage solutions )

Posted By: Reconnoiter

c_scan ( different explo damage solutions ) - 08/25/14 11:30

Hey,

And no the title is not from a new book or such grin , it is a problem that I have with the c_scan function in one of my current projects (fps game).

I create a missile in the form of a disk. I want to give this disk explosion damage but only a circular zone (not in a sphere), so I do the following c_scan:

Code:
if (c_scan(my.x, my.pan, vector(360, 0, 150), SCAN_ENTS | IGNORE_ME | IGNORE_FLAG2 | IGNORE_PASSABLE | IGNORE_WORLD) > 0)
{
....
}



The missile's roll is 0.

The thing is that this checks in a sphere and not in a circular zone relative to the missile's angle for some reason. I tested it several times with large groups of enemies.

Maybe important the mention is that it is a big world in x,y,z coordinates (every is scaled a lot). Could something like that be it? That the large world coordinates messes with a maximum amount of a variable or something like that? Or, perhaps more likely, I am just making a stupid mistake here? Or something else?

Thanks.
Posted By: pararealist

Re: c_scan and a big world - 08/25/14 20:00

sector.y vertical scan sector in degrees, or 0 for a circular scan cone.

try using 1.
Posted By: Reconnoiter

Re: [ many explosion damage solutions ] c_scan and a big world - 08/25/14 20:03

I found this quote from Superku:

Quote:
-400000...400000 level size is way too big. var ranges from approx. -1024567 to 1024567 (or 999999, that's easier to remember). When you calculate with these huge values, there will probably be many "math" problems: For instance when using vec_dist, the function squares 400000 which is of course above 999999. As a result vec_dist will return nothing useful, so other instructions will do the same.
Scale your whole level down e.g. by 90%.

(I feel like I'm talking rubbish, but this should be correct.)


Maybe I should rescale everything. I am hesitating, there are alot of models to rescale than eek . The map size is:
x -> 500 to 27500
y -> 4500 to 30500
z -> -7000 to 0

(the weird coordinates are cause of the sun positions limitations)

-edit, @pararealist, ty going to try that

-edit 2, @pararealist, setting it 1 (like vector(360, 1, 500)) hits nothing. Setting to e.g. 30 or higher (like vector(360, 30, 500)) hits everything like it does a sphere check.
Posted By: rayp

Re: c_scan and a big world - 08/25/14 23:28

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.
Code:
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_dist


Heres a simple example of a "selfmade c_scan / explosion without c_scan" ( not tested but iam pretty sure it'll compile n run ):
Code:
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":
Code:
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 ):
Code:
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
Posted By: Reconnoiter

Re: c_scan and a big world - 08/26/14 09:46

Awesome rayp! Its like christmas came early this year laugh . First going to try that draw_point3d function.
Posted By: alibaba

Re: c_scan and a big world - 08/26/14 10:11

Or a combination of EVENT_DETECT and vec_to_ent may also work.
In the event function you do something like this:

VECTOR temp;
vec_set(temp.x,you.x);
vec_to_ent(temp.x,my.x);
if(temp.z==0)
{
... some code
}

i guess this would also check in a circular plane.
Posted By: Reconnoiter

Re: c_scan and a big world - 08/26/14 10:45

Quote:

Great 4 debugging traces or scans ( some may not know yet ):
Code:

c_trace ()... / c_scan ()...
if (HIT_TARGET) draw_point3d (target.x, vector (50, 50, 255), 100, 3);

Displays a red point, one frame long, at "target"s - vector - position.
, how to make this in a while for a group? I have it now for one ent permanently but can't seem to do it for a whole group:

Code:
c_scan...
if (HIT_TARGET) 
{
VECTOR target_vec;
vec_set(target_vec, target.x);
while (1) { draw_point3d (target_vec, vector (50, 50, 255), 100, 3); wait(1); }
}



@alibaba, thats a smart idea. My only question with this is if particle creation is allowed in event functions? I remember reading in the manual that I can't do things like ent_create etc. in events, so I thought that included things like effect (...).
Posted By: alibaba

Re: c_scan and a big world - 08/26/14 12:11

I see no reason for not being allowed to create particles in an event.
Best way is trying and seeing if it throws out an error.
Posted By: Reconnoiter

Re: c_scan and a big world - 08/26/14 20:11

Earlier I had particle functions in my events, the game was less stable than. The manual (v8.45) says under the event section:

Quote:

it shouldn't perform instructions that can trigger events itself, displace entities, start particles or change anything else in the level.
Posted By: alibaba

Re: c_scan and a big world - 08/26/14 20:16

I always understood it that way that you shouldnīt use functions in events that can trigger events itself, for example a second scan in the detect event. Because if you do that you would have an endless loop of detect events.
But particles should have no side effects.
Posted By: rayp

Re: c_scan and a big world - 08/26/14 21:36

Dont create particles in events, neither create / remove ents in events !!! bad, 2 scriptcrash leading ( somehow...sometime ), idea.

btw. calling c_scan in a while, isnt a good idea aswell. at least, use some interval to perform the c_scan. "c_scanning" every frame is a very slow solution.

About the questions ( hope it helps, just written it not tested )
Code:
// -------------------------------------------------------------------------------------------------------------------------
#define  spawn_blood_particle  skill96    // 1 = spawn particles ( like below ) / ents whatever...
#define  id                    skill95    // 4ex: my.id = id_cat; ... my.id = id_healthpack; ... my.id = id_explosion;
#define  id_explosion             1001    // identification - markers. "#define id_2ndmarker  1002" ... and so on
// -------------------------------------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------------------------------
action AnyExplodingEnt_WED(){             // entity that performs the c_scan, the explosion, the gas - barrel 4ex ^^
   my.id = id_explosion;                  // identification of this entity, in this case, its marked as explosion
   while (my){                            // main - while of "explosion - creating entity"
      .
      ..
      ...
      // ---=[ !!! CAREFULL, BAD IDEA: PERFORMING C_SCAN EVERY FRAME : SLOW = S*** ^^ !!! ]=--------------------------------
      if (c_scan (...)){                                           // c_scan's result > 0 means: we've found something
         draw_point3d (target.x, vector (50, 50, 255), 100, 3);    // draw red dot ( one frame only )
         if (you){                                                 // scan detected valid entity? then you = detected ent!
            you.health = 0;                                        // 4ex: kill the scanned entity, whatever u want 2 do
          //effect (blood_effect, 10, you.x, nullvector);          // <- normally, good place 2 spawn particles here, btw
         }
      }
      ...
      ..
      .
      wait (1);
   }
   wait (1);
   ptr_remove (me);
}
// -------------------------------------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------------------------------
void blood_effect (PARTICLE *p) { ... }                                // your particle effect startup function
// -------------------------------------------------------------------------------------------------------------------------
void _myevent_scan(){                                                  // example event that spawns particles when triggered
   if (event_type == EVENT_SCAN) if (you) if (you.id == id_explosion)  // only react 2 scans from explosion-ents (+id-check)
      my.spawn_blood_particle = 1;                                     // as u can see, we spawn parts outside the event :O
}
// -------------------------------------------------------------------------------------------------------------------------
action Way2CreateParts_WED(){            // dont exceed ( +- [not sure atm] ) 19 chars! yes, this sucks ... confirmed.
   set (my, POLYGON);                    // use polygonal hull ( why not? )
   my.emask |= ENABLE_SCAN;              // react on c_scan - requests
   my.event  = _myevent_scan;            // force this event / void 2 run, triggered by any performed c_scan in range
   while (my){                           // the main - while of the "cow, monster, hero ... whatever" - example
      .
      ..
      ...
      if (my.spawn_blood_particle){                                    // set to 1 in the event, thats the magic trick
         my.spawn_blood_particle = 0;                                  // without this our entity wouldnt stop 2 blood ^^
	 VECTOR _temp;   	                                       // local temp vector holding effect's direction
	 vec_set (_temp, vector (normal.x, 0, 0));                     // part's direction correction, optional of course
         effect  (blood_effect, 10 + random (10), my.x, _temp);        // finally, let blood spray / spawn the particles
      }
      ...
      ..
      .
      wait (1);
   }
   wait (1);
   ptr_remove (me);
}
// -------------------------------------------------------------------------------------------------------------------------



Peace
Posted By: alibaba

Re: c_scan and a big world - 08/26/14 21:55

There is no need for c_scan in a while loop.
Just a cleve combining of EVENT_IMPACT and EVENT_DETECT plus what iīve written before.
Pseudocode:
Code:
void MissleEvent()
{
	if(event_type==EVENT_IMPACT)
	{
		c_scan(my.x,my.pan,vector(360,0,400),whateveryouwanttoignore);ī
		wait(1);
		my.event=NULL;
		safe_remove(me);
	}
	if(event_type==EVENT_DETECT)
	{
		VECTOR temp;
		vec_set(temp.x,you.x);
		vec_to_ent(temp.x,you);
		if(temp.z==0)
		{
			//KILL EVERYTHING AND CREATE PARTICLES
		}
	}
}

action Missle()
{
	my.emask |= ENABLE_IMPACT | ENABLE_DETECT;
	my.event=MissleEvent;
	while(me)
	{
		//some ballistics code or something
		wait(1);
	}
}

Posted By: rayp

Re: c_scan and a big world - 08/26/14 22:29

Yes, as i said its a bad (in almost all cases) useless idea. But maybe he wants more then the simple chain - reaction - explosion, we dont know for sure yet. ^^

Another simple way ( if its up2 "barrel explosions" ), nearly the same script as Alibaba posted, in green
Code:
#define health     skill100
#define id         skill99
#define id_barrel  1234

void _event_barrel(){
   if (event_type == EVENT_SCAN || event_type == EVENT_IMPACT) if (you) if (you.id == id_barrel) my.health = 0;
}

//skill1 BarrelHealth 100
action BarrelExplode_WED(){
   set (my, POLYGON);
   my.id     = id_barrel;
   my.emask |= (ENABLE_SCAN | ENABLE_IMPACT); // impact: 4ex use ents as bullets ( 4my taste better than using c_trace btw )
   my.event  = _event_barrel;
   if (my.skill1) my.health = my.skill1       // takes value from WED's settings panel
   else           my.health = 50 + integer (random (50));
   while (my.health){

      // if u want, add more code here. maybe barrel's idle animation lol

      wait (1);
   }
   my.event = NULL;
   set (my, INVISIBLE | PASSABLE); // ghostmode
   c_scan (my.x, my.pan, vector (360,0, 150 + random (250)), SCAN_ENTS | IGNORE_ME | IGNORE_PASSABLE);

   // put your "BOOM - code" here ^^ ...like playing explosion sounds etc.

 /*
   // example: wait until sound was played ( via handle )
   var _sndhandle = 0;
   _sndhandle     = ent_playsound (me, snd_explo, 200);
   while (snd_playing (_sndhandle)) wait (1);
*/
   wait (-1);
   ptr_remove (me);
}



Greets
Posted By: Reconnoiter

Re: c_scan and a big world - 08/27/14 10:45

Quote:
Yes, as i said its a bad (in almost all cases) useless idea. But maybe he wants more then the simple chain - reaction - explosion, we dont know for sure yet. ^^


The code is for a disk sized projectile that the player can fire and that deals full damage to the main target and half in explosion damage in a circular zone. Next to damaging the enemy/entity + chance to stun, it needs to be able to create particles as gore (fountains of blood grin ). For the impact event I got everything working, but I still needed to get the explosion/event_scan part working correctly.

I had trouble getting the draw_point3d code correctly to debug my c_scan. I now used this in the entity's event (its probably bad coding I know, I removed it now, it was only for testing):

Code:
if (event_type == EVENT_SCAN)	
{
 if (you.DAMAGE > 0 && is(you,FLAG2)) 
 {	
  ...damage etc... 
  wait(1);
  while (1) 
  { 
  draw_point3d (my.x, vector (50, 50, 255), 100, 3); 
  wait(1); 
  }
 }
}



... and that shows that the horizontal scan sector and vertical scan sector part part of the c_scan function is incredible buggy/inconsistent or something else is wrong with my map that makes it buggy. Cause often the dots don't get created when I hit an enemy in the explosion range.

So I think I will just entirely ignore c_scan for this one and go with your before first mentioned trick Rayp; for + ent_next + vec_dist within a function that I call from the missile action. I will comment again as soon as I got it working.

For some reason I always tend to mess things up with c_scans in projects no matter how many tutorials + examples I have read about it. Same goes a bit for c_trace, but to a lesser extent.
Posted By: rayp

Re: c_scan and a big world - 08/28/14 02:42

well dont know if i understood the problem with c_scan correct sry. i go in my bed now ^^
Quote:
The code is for a disk sized projectile that the player can fire and that deals full damage to the main target and half in explosion damage in a circular zone.
...but if u combine all tips together, maybe it looks like this grin , a nice rocket - like projectile ( no c_scan used ):
Code:
#define health      skill100
#define _lifetime   skill99    // lifetime of the bullet, the flying projectile
#define _removeable skill98    // 1 = c_explode running  0 = ok, all done, remove now

void c_explode (ENTITY* _ent, _explorange){ // usage: c_explode (me, 300); <- explosion @ me's Position with range of 300
   if (!_ent) return;
   var _stored_you =    0; if (you) _stored_you = handle (you); // saves handle...
   for (you = ent_next (NULL); you; you = ent_next (you)){
      if (!_ent) break;
      var _dist2ent = 0; _dist2ent = _explorange + 1; // always start "false"
      _dist2ent = vec_dist (_ent.x, you.x);
      if (you.health && !you._lifetime){
         trace_mode = (IGNORE_ME | IGNORE_PASSABLE | USE_POLYGON);
         if (_dist2ent < _explorange) if (c_trace (_ent.x, your.x, trace_mode)){
            if (HIT_TARGET) draw_point3d (target.x, vector (50, 50, 255), 100, 3);
            you.health -= dist2ent / 2; // less dist? more damage!
         }
      }
   }
   if (_stored_you) you = ptr_for_handle (_stored_you);        // ...restores handle
   if (_ent) _ent._removeable = 1;
}
void _event_flying_bullet(){
   if (event_type == EVENT_IMPACT || event_type == EVENT_ENTITY) my.health = 0; // BOOOM!
}
void _flying_bullet(){
   my.group     =   1;                   // we'll ignore, bullets wont block each other
   my.health    =   1;
   my._lifetime = 100;
   my.emask    |= (ENABLE_IMPACT | ENABLE_ENTITY);
   my.event     = _event_flying_bullet;
   if (you) vec_set (my.pan, you.pan);   // you = entity that spawned this bullet
   set     (my, POLYGON);                // or use custom hull, often the better choice
   while (my.health && my._lifetime){
      move_mode = (IGNORE_ME | IGNORE_PASSABLE | IGNORE_YOU);
      c_ignore    (1, 0);                // bullets ignore bullets
      c_move      (me, vector (20 * time_step, 0, 0), nullvector, move_mode);
      my._lifetime -= time_step;
      wait (1);
   }
   my.event = NULL;
   set        (my, INVISIBLE | PASSABLE);
   c_explode  (me, 300);                  // init explosion
   while      (!my.removeable) wait (1);  // wait until c_explode is done
   wait       (1);
   ptr_remove (me);                       // finally, remove projectile
}
action Hero_WED(){                        // example how to create a bullet from player
   my.health      = 100;
   my.group       =   1;                  // the bullets ignore the player
   var _snd_shoot =   0;                  // simply holds handle of sound file later
   while (my.health){
      .
      ..
      ...
      if (key_ctrl || mouse_left) if (!snd_playing (_snd_shoot)){
         _snd_shoot = snd_play (sound_playerfires_rocket, 80, 0);
         ent_create ("bullet.mdl", vector (my.x, my.x, my.z), _flying_bullet);
      }
      ...
      ..
      .
      wait (1);
   }
}

did not test, looks like it works. but finally, i need some sleep. ^^

edit: you.health -= _dist2ent / 2 is bullshit atm, will add working line, in near future.

Greets
Posted By: Reconnoiter

Re: c_scan and a big world - 08/28/14 13:43

Hi,

I wrote some new code which doesn't use c_scan or c_trace and it almost works perfectly and it seems fairly fps friendly. There is still 1 problem, I can't seem to get the c_scan-like horizontal and vertical sector check working. The code is below, thanks alot by the way for all your time so far. I call the function once when the missile explodes:

Code:
//*CUSTOM explosion hit event*//
//for player weapons explosions//

function enemy_hitexplosion()
{
VECTOR scan_sector, enemypos_vec;

 for (you = ent_next (NULL); you; you = ent_next (you))
 {
  if (you.group == 3) // == ENEMY
  { 
   if (you.STATE != 5) //NOT DEAD
   {
    if (vec_dist(my.x, you.x) < my.AREAOFEFFECT) //WITHIN DISTANCE
    {
    //simulates c_scan sector scan	
    vec_set(scan_sector, vector(my.AREAOFEFFECT, my.AREAOFEFFECT, my.AREAOFEFFECT));		
    if (my.WEAPONSELECTED == 5) scan_sector.z = 50;
    vec_set(enemypos_vec, you.x);
    vec_to_ent(enemypos_vec, my);
    
    //WITHIN SECTOR RANGE
    if (enemypos_vec.x < my.x + scan_sector.x && enemypos_vec.x > my.x - scan_sector.x &&
     enemypos_vec.y < my.y + scan_sector.y && enemypos_vec.y > my.y - scan_sector.y &&
     enemypos_vec.z < my.z + scan_sector.z && enemypos_vec.z > my.z - scan_sector.z) 
    {
     //damage + effect + sound	
     effect(BloodGreen_Effect_base,6 + integer(random(4)),you.x,nullvector);
     ...
     //stun + death (on server)
     ...
    }    
    }
   }
  } 		
 }	
}



ps: the vec_dist check could be ommitted but I purely put it there to save fps (less vec_to_ent and vec_set has to be triggerred than).
Posted By: Reconnoiter

Re: c_scan and a big world - 08/30/14 11:49

Anyone? This is the last issue I have with the explosion. I have searched the AUMs but can't find anything about vec_to_ent. Maybe I am doing it wrong?

I want to compare the enemy position and angle relative to the missile's position and angle.
Posted By: Wjbender

Re: c_scan and a big world - 08/30/14 13:24

can you not just rotate a geometric box wich is as long as the radius of affect ,around the explosion centre ,then for every entity it touches during the 360 sweep , check the distance to the entity from the explosion centre , based on the distance then act accordingly ...

just a theoretical answer..
Posted By: alibaba

Re: c_scan and a big world - 08/30/14 14:04

i guss this line
Code:
//WITHIN SECTOR RANGE
    if (enemypos_vec.x < my.x + scan_sector.x && enemypos_vec.x > my.x - scan_sector.x &&
     enemypos_vec.y < my.y + scan_sector.y && enemypos_vec.y > my.y - scan_sector.y &&
     enemypos_vec.z < my.z + scan_sector.z && enemypos_vec.z > my.z - scan_sector.z)



should look more like this:

Code:
//WITHIN SECTOR RANGE
    if (you.x < my.x + scan_sector.x && you.x > my.x - scan_sector.x &&
     you.y < my.y + scan_sector.y && you.y > my.y - scan_sector.y &&
     enemypos_vec.z < 10&& enemypos_vec.z > -10)



I guess this should work. This will check all ents between -10 and 10 of height.
You problem was (i guess) that you compared the relative x and y coordinates with absolute x and y coordinates.
Posted By: Reconnoiter

Re: c_scan and a big world - 08/30/14 18:39

@Wjbender, funny solution. What I am wondering is though if the collision would be good enough. If I can do it as an almost sphere collision than that would be nice (a retangle block would be less precise on 2 sides when rotating). Maybe the NARROW flag.

@alibaba, yes that code was indeed the problem. But I need to compare the position relatively. Cause otherwise, if I e.g. do "my.tilt = 60;", the explosion's angle does not change. While I want it to rotate properly with the missile's angle. Its for a fps game.
Posted By: alibaba

Re: c_scan and a big world - 08/30/14 20:14

So is this solved?
If not, iīll create an example code for you.
Posted By: Reconnoiter

Re: c_scan and a big world - 08/30/14 21:01

Originally Posted By: alibaba
So is this solved?
If not, iīll create an example code for you.
, no I cant seem to get the scan relative of the missile's position and angle. If you have examples than great laugh .
Posted By: alibaba

Re: c_scan and a big world - 08/30/14 21:57

Here is a working example, i tried to comment and explain as good as i could and tried my best to show the problem.
Just copy the code into an empty .c file and run it. No models whatsoever needed:
Code:
#include <acknex.h>
#include <default.c>

void Barrel()
{
	//Just a placeholder
	set(my,FLAG8);
	my.skill1=100;
	while(my.skill1>0)
	{
		wait(1);
	}
	safe_remove(me);
}

void create_barrel()
{
	VECTOR to;
	vec_set(to,mouse_dir3d);
	vec_scale(to,1000); // set a range
	vec_add(to,mouse_pos3d);
	c_trace(mouse_pos3d,to,0);
	if(trace_hit)
	//This wonīt work, because entity is too high!
	//ent_create(CUBE_MDL,vector(target.x,target.y,target.z+20),Barrel);
	//This will work
	ent_create(CUBE_MDL,vector(target.x,target.y,target.z+10),Barrel);
}
var RocketRange=100;
var RocketScanHeight=10;
 
void HitEvent()
{
	//If hit something
	if(event_type==EVENT_IMPACT||event_type==EVENT_ENTITY)
	{
		//The Problem is here. If you comment out this line, then youīll see that the scan-circle 
		//is rotated into the ground, so you got like no chance to scan anything. To really have the
		//full scan-range, you need to reset itīs rotation
		vec_set(my.pan,nullvector);
		//Scan around
		c_scan(my.x,my.pan,vector(360,0,RocketRange),IGNORE_PASSABLE|IGNORE_ME);
		//And tell the rocket you hit something
		my.skill2=1; 
		//You can remove this line, itīs just to show you the range of the rockets
	//	wait(-1);
		//Now we can remove everything
		my.skill2=2;
	}
	//If scanned something
	if(event_type==EVENT_DETECT)
	{
		//And you are marked as enemy
		if(is(you,FLAG8))
		{
			//And you are withing the height between -10 and 10
			VECTOR temp;
			vec_set(temp.x,you.x);
			vec_to_ent(temp.x,my);
			if(abs(temp.z)<RocketScanHeight)
			{
				//set you health to 0
				you.skill1=0;
			}
		}
	}
}
void shoot_rocket(VECTOR* targetVec)
{
	//We have to save the parameter in order not to lose it
	VECTOR RocketTarget;
	vec_set(RocketTarget,targetVec);
	//No create the rocket
	ENTITY* RocketEnt=ent_create(CUBE_MDL,vector(player.x,player.y,player.z+50),NULL);
	//scale it down
	vec_scale(RocketEnt.scale_x,0.2);
	//Make it react to touches and detected entites
	RocketEnt.emask|=ENABLE_ENTITY|ENABLE_IMPACT|ENABLE_DETECT;
	RocketEnt.event=HitEvent;
	//The variable for acceleration
	var RocketSpeed=0;
	
	//The range indicator
	ENTITY* range=ent_create(SPHERE_MDL,my.x,NULL);
	//Scale it to the range of the rocket
	vec_scale(range.scale_x,RocketRange/8);
	range.scale_z=RocketScanHeight/8;
	//make it transparent
	set(range,TRANSLUCENT|PASSABLE);
	range.alpha=50;
	
	//Fly as long as we hit nothing
	while(RocketEnt.skill2==0)
	{
		//Target our destination
		vec_to_angle(RocketEnt.pan,vec_diff(NULL,RocketTarget.x,RocketEnt.x));
		//Accelerate to get the "rocket effect"
		accelerate(RocketSpeed,0.5,0);
		c_move(RocketEnt,vector(RocketSpeed,0,0),nullvector,IGNORE_PASSABLE|USE_POLYGON);
		
		//set the range indicator to rockets position and orientation
		vec_set(range.x,RocketEnt.x);
		vec_set(range.pan,RocketEnt.pan);
		
		//You can uncomment this line to really see how the rotation makes a difference
		//RocketEnt.roll+=5*time_step;
		wait(1);
	}
	//When we hit something, wait until we can remove it
	while(RocketEnt.skill2==1)wait(1);
	//Reset the event and remove everything
	RocketEnt.event=NULL;
	safe_remove(range);
	safe_remove(RocketEnt);
}

void playerEnt()
{
	player=me;
	VECTOR to;
	var RocketTime=0;
	while(1)
	{
		draw_text("Shoot with [mouse_left]\ncreate barrels with [mouse_right]\nmove with WASD",0,0,COLOR_WHITE);
		//Mark our target 
		vec_set(to,mouse_dir3d);
		vec_scale(to,1000); // set a range
		vec_add(to,mouse_pos3d);
		c_trace(mouse_pos3d,to,0);
		if(trace_hit)
		draw_point3d(vector(target.x,target.y,target.z+10),COLOR_RED,100,10);
		
		//Shoot 2 rockets every second
		if(mouse_left&&RocketTime>0.5)
		{
			shoot_rocket(target.x);
			RocketTime=0;
		}
		RocketTime+=time_step/16;
		//Rotate to the mouse pointer
		vec_to_angle(my.pan,vec_diff(NULL,target.x,my.x));
		c_move(my,vector(3*(key_w-key_s),3*(key_a-key_d),0),vector(0,0,-1),GLIDE);
		wait(1);
	}
	
}

void main()
{
	fps_max=60;
	level_load("");
	//Let the mouse have influence
	mouse_mode=4;
	//Create the playground
	you=ent_create(CUBE_MDL,nullvector,NULL);
	you.scale_x=50;
	you.scale_y=50;
	set(you,POLYGON);
	//set camera position
	vec_set(camera.x,vector(0,0,500));
	camera.tilt=-90;
	//Create the player
	ent_create(CUBE_MDL,vector(0,0,10),playerEnt);
	on_mouse_right=create_barrel;
}

Posted By: Reconnoiter

Re: c_scan and a big world - 08/31/14 19:42

First I want to thank you all for your angelic patience. I know it is not always easy to help me with my code and sometimes it's a long journey grin.

I did alot of testing today with the various solutions offered:

@Wjbender, while I really like the idea of your method, the results are funny when using a disk shape as an explosion. When firing the horizontal disk, enemies walking towards the player will move over it (even while I do 1 ignore_group before the enemy's c_move and 1 before their c_trace). Maybe my problem is not using the right engine function to trigger event_impact (I have tried c_rotate and c_move). But next to that it seems to work good enough. I have c&p the code below.

@alibaba, your sample that not seem to work always eek. If I comment "vec_set(my.pan,nullvector);" (found in the HitEvent function) and e.g. set "RocketEnt.roll = 90;" in the shoot_rocket action, it works better but still not always.


My version of Wjbender's-idea-like explosion (created at the end of the player missile):

Code:
action explosion_playermissile()
{
 VECTOR scan_sector;	
 my.group = 1; //for player projectiles	
 set(my,FLAG2);	
 my.WEAPONSELECTED = you.WEAPONSELECTED;
 my.DAMAGE = you.DAMAGE;
 my.AREAOFEFFECT = you.AREAOFEFFECT;
 vec_set(my.pan,you.pan);
 
 vec_set(scan_sector, vector(my.AREAOFEFFECT, my.AREAOFEFFECT, my.AREAOFEFFECT));		
 if (my.WEAPONSELECTED == 5) scan_sector.z = 30;

 my.scale_x = scan_sector.x /45;
 my.scale_y = scan_sector.y /45;
 my.scale_z = scan_sector.z /45;
 wait(1);
 c_setminmax(me);
 
 var angle;
 for (angle = 0; angle < 360; angle += 30) 
 {
 ang_rotate(my.pan,vector(angle, 0, 0));
 // vec_add(my.pan, vector(-5, -5, -5));	
 // c_rotate(my, vector(5,5,5), IGNORE_FLAG2 | IGNORE_PASSABLE | IGNORE_WORLD);
 vec_add(my.x, vector(-5, -5, -5));
 c_move(my, nullvector, vector(5,5,5), IGNORE_FLAG2 | IGNORE_PASSABLE | IGNORE_WORLD);
 wait(1);
 }	
 ent_remove(me);
 	
}

Posted By: alibaba

Re: c_scan and a big world - 09/01/14 11:45

I donīt know why you removed the line.
The code works as it should, maybe you place the barrels on each other.
Posted By: Wjbender

Re: c_scan and a big world - 09/01/14 12:56

I have tested the code as given by alibaba it does work , however it does only work when the rocket reaches the destination target , it does not account
for impacts in route and maby thats what the op
finds as a problem during testing ?

secondly , the rockets impact way before the target area
(possibly not that important for now)

if thats fixed maby it would work ..

Code:
void Barrel()
{
	//Just a placeholder
	set(my,FLAG8);
	my.skill1=100;
	while(my.skill1>0)
	{
		VECTOR pos;
		vec_set(pos,my.x);
		vec_to_screen(pos,camera);
		draw_text(str_printf(NULL,"%i",(long)my.z),pos.x,pos.y,COLOR_WHITE);
		wait(1);
	}
	safe_remove(me);
}



and yes you have to keep an eye on the height in alibab's example,i have include a text draw call in this function so
if you test you should see that any barrels too high would not
be detected , upon creation of those barrels it seems the
height is around 17 or 18..
Posted By: Reconnoiter

Re: c_scan and a big world - 09/01/14 17:16

ok thanks guys! This has become a very informative thread concerning explosion damage with many different possible solutions. I will see if I can edit this thread's name so more people searching on explosions will find it.

-edit, can't, maybe a moderator can change it to e.g. [ many explosion damage solutions ] or such for others?
© 2024 lite-C Forums