Oh, hence the line
Guess there is no other way besides waiting for the next release.
Can't seem to find anything relevant in MCO.
Either way, the script goes on to this
Code: Select all
rpgent(rpgobj *_ro, rpgclient &_cl, const vec &_pos, float _yaw, int _maxspeed = 40, int _type = ENT_AI) : ro(_ro), cl(_cl), lastaction(0), lastpain(0), attacking(false), lastpickupmillis(0), checkpoint(-1), enemy(NULL), npcstate(R_STARE), trigger(0), sink(0)
{
o = _pos;
home = _pos;
yaw = _yaw;
maxspeed = _maxspeed;
type = _type;
enemy = &cl.player1;
magicproj.setsize(0);
}
float vecyaw(vec &t) { return -(float)atan2(t.x-o.x, t.y-o.y)/RAD+180; }
static const int ATTACKSAMPLES = 32;
void tryattackobj(rpgobj &eo, rpgobj &weapon)
{
if(!eo.s_ai || (eo.s_ai==ro->s_ai && eo.ent!=enemy)) return;
rpgent &e = *eo.ent;
if(e.state!=CS_ALIVE) return;
vec d = e.o;
d.sub(o);
d.z = 0;
if(d.magnitude()>e.radius+weapon.s_maxrange) return;
if(o.z+aboveeye<=e.o.z-e.eyeheight || o.z-eyeheight>=e.o.z+e.aboveeye) return;
vec p(0, 0, 0), closep;
float closedist = 1e10f;
loopj(ATTACKSAMPLES)
{
p.x = e.xradius * cosf(2*M_PI*j/ATTACKSAMPLES);
p.y = e.yradius * sinf(2*M_PI*j/ATTACKSAMPLES);
p.rotate_around_z((e.yaw+90)*RAD);
p.x += e.o.x;
p.y += e.o.y;
float tyaw = vecyaw(p);
normalize_yaw(tyaw);
if(fabs(tyaw-yaw)>weapon.s_maxangle) continue;
float dx = p.x-o.x, dy = p.y-o.y, dist = dx*dx + dy*dy;
if(dist<closedist) { closedist = dist; closep = p; }
}
if(closedist>weapon.s_maxrange*weapon.s_maxrange) return;
weapon.useaction(eo, *this, true);
}
#define loopallrpgobjsexcept(ro) loop(i, cl.os.set.length()+1) for(rpgobj *eo = i ? cl.os.set[i-1] : cl.os.playerobj; eo; eo = NULL) if((ro)!=eo)
void tryattack(vec &lookatpos, rpgobj &weapon)
{
if(lastmillis-lastaction<weapon.s_attackrate) return;
lastaction = lastmillis;
switch(weapon.s_usetype)
{
case 1:
if(!weapon.s_damage) return;
weapon.usesound(this);
loopallrpgobjsexcept(ro) tryattackobj(*eo, weapon);
break;
case 2:
{
if(!weapon.s_damage) return;
weapon.usesound(this);
vec flarestart = o;
flarestart.z -= 2;
particle_flare(flarestart, lookatpos, 600, PART_STREAK, 0x7FFF00); // FIXME hudgunorigin(), and shorten to maxrange
float bestdist = 1e16f;
rpgobj *best = NULL;
loopallrpgobjsexcept(ro)
{
if(eo->ent->state!=CS_ALIVE) continue;
if(!intersect(eo->ent, o, lookatpos)) continue;
float dist = o.dist(eo->ent->o);
if(dist<weapon.s_maxrange && dist<bestdist)
{
best = eo;
bestdist = dist;
}
}
if(best) weapon.useaction(*best, *this, true);
break;
}
case 3:
if(weapon.s_maxrange) // projectile, cast on target
{
if(!ro->usemana(weapon)) return;
vec dir;
float worlddist = lookatpos.dist(o, dir);
dir.normalize();
magicproj.add(new mproj(o, dir, &weapon, min(float(weapon.s_maxrange), worlddist)));
}
else
{
weapon.useaction(*ro, *this, true); // cast on self
cl.fx.addfx(weapon.s_effect, *ro->ent);
}
break;
}
}