void effect::drawcone(vec &o, vec dir, vec &axis, int angle, float radius, float size, int type, int elapse)
{
	if(size <= 0) return;

	size *= this->size;
	int fade, gravity, num;
	setvars(this, type, fade, gravity, num);

	num *= angle * (particle == PART_STREAK || particle == PART_LIGHTNING ? 1 : partmul) /
		size / 30 * (elapse ? logf(elapse) / 3 : 1);
	num = max<int>(1, num);

	loopi(num)
	{
		vec ray = vec(dir).rotate(rnd(angle + 1) * RAD, axis).rotate(rnd(360), dir).mul(radius);
		switch(particle)
		{
			case PART_EXPLOSION:
			case PART_EXPLOSION_BLUE:
				ray.mul(rnd(101)/100.f).add(o);
				particle_fireball(ray, size, particle, fade, colour, size);
				break;
			case PART_STREAK:
			case PART_LIGHTNING:
				if(!curtime) return;
				particle_flare(o, ray.add(o), fade, particle, colour, size);
				break;
			default:
				ray.mul(rnd(101)/100.f).add(o);
				particle_splash(particle, 2, fade, ray, colour, size, max<int>(1, size * 2), gravity);
				break;
		}
	}
}
void effect::drawaura(rpgent *d, float size, int type, int elapse)
{
	if(size <= 0) return;

	size *= this->size;
	int fade, gravity, num;
	setvars(this, type, fade, gravity, num);

	num *= .2 * PI * d->radius / (1 + size) * partmul * (elapse ? logf(elapse) / 3 : 1);
	if(elapse && !num && rnd(int(10 / partmul))) return; //sometimes particles should not be drawn
	num = max<int>(1, num);

	loopi(num)
	{
		vec pos = vec(rnd(360) * RAD, 0).mul(d->radius + size).add(d->feetpos());
		switch(particle)
		{
			case PART_EXPLOSION:
			case PART_EXPLOSION_BLUE:
				particle_fireball(pos, size, particle, fade, colour, size);
				break;
			case PART_STREAK:
			case PART_LIGHTNING:
				if(!curtime) return;
				particle_flare(pos, vec(0, 0, d->eyeheight + d->aboveeye).add(pos), fade, particle, colour, size);
				break;
			default:
				if(gravity >= 0)
					pos.add(vec(0, 0, d->eyeheight + d->aboveeye));

				particle_splash(particle, 2, fade, pos, colour, size, max<int>(1, size * 2), gravity);
				break;
		}
	}
}
void effect::drawwield(vec &from, vec &to, float size, int type, int elapse)
{
	if(size <= 0) return;

	if(particle == PART_STREAK || particle == PART_LIGHTNING)
	{
		drawline(from, to, size, type, elapse);
		return;
	}

	size *= this->size;
	int fade, gravity, num;
	setvars(this, type, fade, gravity, num);

	num *= partmul * (elapse ? (logf(elapse) / 3) : 1) / (1 + size);

	if(elapse && !num && rnd(int(10 / partmul))) return;
	num = max<int>(1, num);

	vec delta = vec(to).sub(from);

	loopi(num)
	{
		vec pt = vec(delta).mul((float) rnd(0x10000) / 0xFFFF).add(from);
		switch(particle)
		{
			case PART_EXPLOSION:
			case PART_EXPLOSION_BLUE:
				particle_fireball(pt, size * 2, particle, fade, colour, size * 4);
				break;
			default:
				particle_splash(particle,  2, fade, pt, colour, size, max<int>(1, size * 5), gravity);
		}
	}
}
Пример #4
0
    void rpgent::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);
                particle_splash(PART_SPARK, 200, 250, lookatpos, 0xB49B4B, 0.24f);
                vec flarestart = o;
                flarestart.z -= 2;
                particle_flare(flarestart, lookatpos, 600, PART_STREAK, 0xFFC864, 0.28f);  // 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(magicprojectile) return;     // only one in the air at once
                    if(!ro->usemana(weapon)) return;

                    magicprojectile = true;
                    mpweapon = &weapon;
                    mppos = o;
                    //mpdir = vec(yaw*RAD, pitch*RAD);
                    float worlddist = lookatpos.dist(o, mpdir);
                    mpdir.normalize();
                    mpdist = min(float(weapon.s_maxrange), worlddist);
                }
                else
                {
                    weapon.useaction(*ro, *this, true);   // cast on self
                }
                break;
        }
    }
void effect::drawsplash(vec &o, vec dir, float radius, float size, int type, int elapse)
{
	if(size <= 0) return;

	size *= this->size;
	int fade, gravity, num;
	setvars(this, type, fade, gravity, num);
	num *= .1 * radius / (1 + size) * partmul * (elapse ? logf(elapse) / 3 : 1);
	if(elapse && !num && rnd(int(10 / partmul))) return; //sometimes particles should not be drawn
	num = max(1, num);

	switch(particle)
	{
		case PART_EXPLOSION:
		case PART_EXPLOSION_BLUE:
			particle_fireball(o, radius ? radius : size, particle, fade, colour, size);
			break;
		case PART_STREAK:
		case PART_LIGHTNING:
			if(!curtime) break;

			if(!radius) //assume num == 1
			{
				vec offset = vec(dir).mul(-2 * size).add(o);
				particle_flare(offset, o, fade, particle, colour, size);
			}
			else
			{
				num = (num / 2 + num % 2);
				loopi(num)
				{
					vec offset = vec(rnd(360) * RAD, (90 - rnd(180)) * RAD).mul(radius);
					vec offset2 = vec(rnd(360) * RAD, rnd(360) * RAD).mul(radius);
					particle_flare(vec(o).sub(offset), vec(o).add(offset2), fade, particle, colour, size);
				}
			}
			break;
		default:
			particle_splash(particle, num, fade, o, colour, size, max<int>(1, radius), gravity);
			break;
	}
}
bool effect::drawline(vec &from, vec &to, float size, int type, int elapse)
{
	if(size <= 0) return false;

	size *= this->size;
	int fade, gravity, num;
	setvars(this, type, fade, gravity, num);
	num *= from.dist(to) / (10 * size) * partmul * (elapse ? logf(elapse) / 3 : 1);
	if(particle == PART_STREAK || particle == PART_LIGHTNING)
		num /= 2;

	num = min<int>(min(num, linemaxsteps), from.dist(to) / linemininterval);
	if(!num) return false;
	vec delta = vec(to).sub(from).div(num);

	loopi(num)
	{
		switch(particle)
		{
			case PART_EXPLOSION:
			case PART_EXPLOSION_BLUE:
				particle_fireball(from, size * 2, particle, fade, colour, size * 2);
				break;
			case PART_STREAK:
			case PART_LIGHTNING:
			{
				if(!curtime) return false;
				vec start = vec(rnd(360) * RAD, rnd(360) * RAD).mul(4 * size).add(from);
				vec end = vec(delta).mul(1.5).add(start);

				particle_flare(start, end, fade, particle, colour, size);
				break;
			}
			default:
				particle_splash(particle, 2, fade, from, colour, size, max<int>(1, size * 5), gravity);
				break;
		}
		from.add(delta);
	}

	return true;
}
Пример #7
0
    void rpgent::updateprojectile()
    {
        if(!magicprojectile) return;

        regular_particle_splash(PART_SMOKE, 2, 300, mppos, 0x404040, 0.6f, 150, -20);
        particle_splash(PART_FIREBALL1+mpweapon->s_effectparticle, 1, 1, mppos, mpweapon->s_effectcolor, mpweapon->s_effectsize/100.0f);

        float dist = curtime/5.0f;
        if((mpdist -= dist)<0) { magicprojectile = false; return; };

        vec mpto = vec(mpdir).mul(dist).add(mppos);

        loopallrpgobjsexcept(ro)     // FIXME: make fast "give me all rpgobs in range R that are not X" function
        {
            if(eo->ent->o.dist(mppos)<32 && intersect(eo->ent, mppos, mpto))  // quick reject, for now
            {
                magicprojectile = false;
                mpweapon->useaction(*eo, *this, false);    // cast on target
            }
        }

        mppos = mpto;
    }
Пример #8
0
void demoplaybackstep()
{
    while(demoplayback && lastmillis>=playbacktime)
    {
        int len = gzgeti();
        if(len<1 || len>MAXTRANS)
        {
            conoutf("error: huge packet during demo play (%d)", len);
            stopreset();
            return;
        };
        uchar buf[MAXTRANS];
        gzread(f, buf, len);
        localservertoclient(buf, len);  // update game state
        
        dynent *target = players[democlientnum];
        assert(target); 
        
		int extras;
        if(extras = gzget())     // read additional client side state not present in normal network stream
        {
            target->gunselect = gzget();
            target->lastattackgun = gzget();
            target->lastaction = scaletime(gzgeti());
            target->gunwait = gzgeti();
            target->health = gzgeti();
            target->armour = gzgeti();
            target->armourtype = gzget();
            loopi(NUMGUNS) target->ammo[i] = gzget();
            target->state = gzget();
            target->lastmove = playbacktime;
			if(bdamage = gzgeti()) damageblend(bdamage);
			if(ddamage = gzgeti()) { gzgetv(dorig); particle_splash(3, ddamage, 1000, dorig); };
            // FIXME: set more client state here
        };
        
        // insert latest copy of player into history
        if(extras && (playerhistory.empty() || playerhistory.last()->lastupdate!=playbacktime))
        {
            dynent *d = newdynent();
            *d = *target;
            d->lastupdate = playbacktime;
            playerhistory.add(d);
            if(playerhistory.length()>20)
            {
                zapdynent(playerhistory[0]);
                playerhistory.remove(0);
            };
        };
        
        readdemotime();
    };
    
    if(demoplayback)
    {
        int itime = lastmillis-demodelaymsec;
        loopvrev(playerhistory) if(playerhistory[i]->lastupdate<itime)      // find 2 positions in history that surround interpolation time point
        {
            dynent *a = playerhistory[i];
            dynent *b = a;
            if(i+1<playerhistory.length()) b = playerhistory[i+1];
            *player1 = *b;
            if(a!=b)                                // interpolate pos & angles
            {
				dynent *c = b;
				if(i+2<playerhistory.length()) c = playerhistory[i+2];
				dynent *z = a;
				if(i-1>=0) z = playerhistory[i-1];
				//if(a==z || b==c) printf("* %d\n", lastmillis);
				float bf = (itime-a->lastupdate)/(float)(b->lastupdate-a->lastupdate);
				fixwrap(a, player1);
				fixwrap(c, player1);
				fixwrap(z, player1);
				vdist(dist, v, z->o, c->o);
				if(dist<16)		// if teleport or spawn, dont't interpolate
				{
					catmulrom(z->o, a->o, b->o, c->o, bf, player1->o);
					catmulrom(*(vec *)&z->yaw, *(vec *)&a->yaw, *(vec *)&b->yaw, *(vec *)&c->yaw, bf, *(vec *)&player1->yaw);
				};
				fixplayer1range();
			};
            break;
        };
        //if(player1->state!=CS_DEAD) showscores(false);
    };
};
Пример #9
0
void TargetingControl::determineMouseTarget(bool forceEntityCheck)
{
    targetLogicEntity = NULL;

    TargetingControl::worldPosition = worldpos;

    if (logger::should_log(logger::INFO))
        particle_splash(0, 50, 100, TargetingControl::worldPosition); // Kripken: Show some sparkles where the mouse points - for debug

    if (!editmode && !forceEntityCheck)
    {
        TargetingControl::targetLogicEntity = NULL;
        TargetingControl::targetPosition = TargetingControl::worldPosition;
        has_mouse_target = 0;
    } else {
        static long lastEntityCheck = -1; // Use this to not run an actual entity check more than 1/frame

        if (lastEntityCheck != lastmillis)
        {
            float dist;

            TargetingControl::intersectClosest(camera1->o,
                                               worldpos,
                                               camera1,
                                               dist,
                                               TargetingControl::targetLogicEntity);

            // If not edit mode, ignore the player itself
            if (!editmode && TargetingControl::targetLogicEntity && !TargetingControl::targetLogicEntity->isNone() &&
                    TargetingControl::targetLogicEntity->getUniqueId() == ClientSystem::uniqueId)
            {
                // Try to see if the player was the sole cause of collision - move it away, test, then move it back
                vec save = ClientSystem::playerLogicEntity->dynamicEntity->o;
                ClientSystem::playerLogicEntity->dynamicEntity->o.add(10000.0);

                TargetingControl::intersectClosest(camera1->o,
                                                   worldpos,
                                                   camera1,
                                                   dist,
                                                   TargetingControl::targetLogicEntity);

                ClientSystem::playerLogicEntity->dynamicEntity->o = save;
            }

            has_mouse_target = int(TargetingControl::targetLogicEntity && !TargetingControl::targetLogicEntity->isNone());

            if (has_mouse_target)
            {
                vec temp(worldpos);
                temp.sub(camera1->o);
                temp.normalize();
                temp.mul(dist);
                temp.add(camera1->o);

                TargetingControl::targetPosition = temp;
            } else
                TargetingControl::targetPosition = TargetingControl::worldPosition;

            lastEntityCheck = lastmillis;
        }
    }
}