Пример #1
0
void NegateMagicSpell::LaunchAntiMagicField() {
	
	if(!ValidIONum(m_target))
		return;
	
	for(size_t i = 0; i < MAX_SPELLS; i++) {
		SpellBase * spell = spells[SpellHandle(i)];
		
		if(!spell)
			continue;
		
		if(this == spell)
			continue;
		
		if(m_level < spell->m_level)
			continue;
		
		Vec3f pos = spell->getPosition();
		if(closerThan(pos, entities[m_target]->pos, 600.f)) {
			if(spell->m_type != SPELL_CREATE_FIELD) {
				spells.endSpell(spell);
			} else if(m_target == PlayerEntityHandle && spell->m_caster == PlayerEntityHandle) {
				spells.endSpell(spell);
			}
		}
	}
}
Пример #2
0
void PrecalcDynamicLighting(long x0, long z0, long x1, long z1) {

    ARX_PROFILE_FUNC();

    TOTPDL = 0;

    float fx0 = ACTIVEBKG->Xdiv * (float)x0;
    float fz0 = ACTIVEBKG->Zdiv * (float)z0;
    float fx1 = ACTIVEBKG->Xdiv * (float)x1;
    float fz1 = ACTIVEBKG->Zdiv * (float)z1;

    for(size_t i = 0; i < MAX_DYNLIGHTS; i++) {
        EERIE_LIGHT * el = &DynLight[i];

        if(el->exist && el->rgb.r >= 0.f) {
            if(   el->pos.x >= fx0
                    && el->pos.x <= fx1
                    && el->pos.z >= fz0
                    && el->pos.z <= fz1
                    && closerThan(el->pos, ACTIVECAM->orgTrans.pos, ACTIVECAM->cdepth)
              ) {
                el->treat = 1;
                RecalcLight(el);
                PDL[TOTPDL] = el;
                TOTPDL++;

                if(TOTPDL >= MAX_DYNLIGHTS)
                    TOTPDL--;
            }
            else if(el->treat)
                el->treat = 0;
        }
    }
}
bool ControlTargetSpell::CanLaunch()
{
	if(!ValidIONum(m_target)) {
		return false;
	}
	
	long tcount = 0;
	for(size_t ii = 1; ii < entities.size(); ii++) {
		const EntityHandle handle = EntityHandle(ii);
		Entity * ioo = entities[handle];
		
		if(!ioo || !(ioo->ioflags & IO_NPC)) {
			continue;
		}
		
		if(ioo->_npcdata->lifePool.current <= 0.f || ioo->show != SHOW_FLAG_IN_SCENE) {
			continue;
		}
		
		if(ioo->groups.find("demon") == ioo->groups.end()) {
			continue;
		}
		
		if(closerThan(ioo->pos, m_caster_pos, 900.f)) {
			tcount++;
		}
	}
	if(tcount == 0) {
		return false;
	}
	
	return true;
}
Пример #4
0
void EERIE_LIGHT_Apply(EERIEPOLY * ep) {

    if (ep->type & POLY_IGNORE)  return;

    float epr[4];
    float epg[4];
    float epb[4];

    epr[3] = epr[2] = epr[1] = epr[0] = 0;
    epg[3] = epg[2] = epg[1] = epg[0] = 0;
    epb[3] = epb[2] = epb[1] = epb[0] = 0;

    for(size_t i = 0; i < MAX_LIGHTS; i++) {

        EERIE_LIGHT * el = GLight[i];

        if ((el) && (el->treat) && (el->exist) && (el->status)
                && !(el->extras & EXTRAS_SEMIDYNAMIC))
        {
            if(closerThan(el->pos, ep->center, el->fallend + 100.f)) {
                ARX_EERIE_LIGHT_Make(ep, epr, epg, epb, el);
            }
        }
    }

    for (size_t i = 0; i < MAX_ACTIONS; i++)
    {
        if ((actions[i].exist) && ((actions[i].type == ACT_FIRE2) || (actions[i].type == ACT_FIRE)))
        {
            if(closerThan(actions[i].light.pos, ep->center, actions[i].light.fallend + 100.f)) {
                ARX_EERIE_LIGHT_Make(ep, epr, epg, epb, &actions[i].light);
            }
        }
    }

    long nbvert;

    if (ep->type & POLY_QUAD) nbvert = 4;
    else nbvert = 3;

    for(long i = 0; i < nbvert; i++) {
        epr[i] = clamp(epr[i], ACTIVEBKG->ambient.r, 1.f);
        epg[i] = clamp(epg[i], ACTIVEBKG->ambient.g, 1.f);
        epb[i] = clamp(epb[i], ACTIVEBKG->ambient.b, 1.f);
        ep->v[i].color = Color3f(epr[i], epg[i], epb[i]).toBGR();
    }
}
Пример #5
0
static void drawDebugEntities() {
	
	for(size_t i = 1; i < entities.size(); i++) {
		const EntityHandle handle = EntityHandle(i);
		Entity * entity = entities[handle];
		
		if(!entity) {
			continue;
		}
		
		Color color = Color::white;
		bool visible = true;
		switch(entity->show) {
			case SHOW_FLAG_DESTROYED:    continue; // Don't even display the name
			case SHOW_FLAG_IN_INVENTORY: continue;
			case SHOW_FLAG_ON_PLAYER:    continue;
			case SHOW_FLAG_LINKED:       continue;
			case SHOW_FLAG_NOT_DRAWN:    color = Color::magenta; visible = false; break;
			case SHOW_FLAG_HIDDEN:       color = Color::yellow;  visible = false; break;
			case SHOW_FLAG_MEGAHIDE:     color = Color::green;   visible = false; break;
			case SHOW_FLAG_KILLED:       color = Color::red;     visible = false; break;
			case SHOW_FLAG_IN_SCENE:     color = Color::white;   visible = true;  break;
			case SHOW_FLAG_TELEPORTING:  color = Color::blue;    visible = true;  break;
		}
		if((entity->ioflags & IO_CAMERA) || (entity->ioflags & IO_MARKER)) {
			color = Color::gray(0.7f), visible = false;
		}
		if(DRAGINTER == entity) {
			color = Color::white, visible = true;
		}
		
		if(visible) {
			drawDebugBoundingBox(entity->bbox2D, Color::blue);
		}
		
		if(closerThan(entity->pos, player.pos, DebugTextMaxDistance)) {
			
			if(visible && entity->bbox2D.valid()) {
				int x = (entity->bbox2D.min.x + entity->bbox2D.max.x) / 2;
				int y = entity->bbox2D.min.y - hFontDebug->getLineHeight() - 2;
				UNICODE_ARXDrawTextCenter(hFontDebug, Vec2f(x, y), entity->idString(), color);
			} else {
				drawTextAt(hFontDebug, entity->pos, entity->idString(), color);
			}
			
			if(entity->obj) {
				for(size_t j = 0; j < entity->obj->linked.size(); j++) {
					Vec3f pos = actionPointPosition(entity->obj, entity->obj->linked[j].lidx);
					Entity * other = entity->obj->linked[j].io;
					drawTextAt(hFontDebug, pos, other->idString(), Color::cyan);
				}
			}
			
		}
		
	}
	
}
Пример #6
0
void CheckForIgnition(const Vec3f & pos, float radius, bool mode, long flag) {
	
	if(!(flag & 1))
		for(size_t i = 0; i < MAX_LIGHTS; i++) {
			EERIE_LIGHT * el = GLight[i];

			if(el == NULL)
				continue;

			if((el->extras & EXTRAS_EXTINGUISHABLE) && (el->extras & (EXTRAS_SEMIDYNAMIC | EXTRAS_SPAWNFIRE | EXTRAS_SPAWNSMOKE)))
			{
				if((el->extras & EXTRAS_FIREPLACE) && (flag & 2))
					continue;

				if(!fartherThan(pos, el->pos, radius)) {
					if(mode) {
						if (!(el->extras & EXTRAS_NO_IGNIT))
							el->m_ignitionStatus = true;
					} else {
						el->m_ignitionStatus = false;
					}
				}

			}
		}

	for(size_t i = 0; i < entities.size(); i++) {
		const EntityHandle handle = EntityHandle(i);
		Entity * io = entities[handle];

		if(   io
		   && io->show == SHOW_FLAG_IN_SCENE
		   && io->obj
		   && !(io->ioflags & IO_UNDERWATER)
		   && io->obj->fastaccess.fire >= 0
		) {
			if(closerThan(pos, io->obj->vertexlist3[io->obj->fastaccess.fire].v, radius)) {

				if(mode && io->ignition <= 0 && io->obj->fastaccess.fire >= 0) {
					io->ignition = 1;
				} else if(!mode && io->ignition > 0) {
					if(io->obj->fastaccess.fire >= 0) {
						io->ignition = 0; 
						lightHandleDestroy(io->ignit_light);

						if(io->ignit_sound != audio::INVALID_ID) {
							ARX_SOUND_Stop(io->ignit_sound);
							io->ignit_sound = audio::INVALID_ID;
						}
					}
					else if(!(flag & 2))
						io->ignition = 0.00001f;
				}
			}
		}
	}
}
Пример #7
0
static void drawDebugEntityPhysicsCylinders() {
	for(size_t i = 1; i < entities.size(); i++) {
		const EntityHandle handle = EntityHandle(i);
		Entity * entity = entities[handle];
		
		if(!entity || !closerThan(entity->pos, player.pos, DebugPhysicsMaxDistance))
			continue;
		
		drawDebugCollisionShape(entity->obj);
		drawDebugEntityPhysicsCylinder(entity);
	}
}
Пример #8
0
void ComputeTileLights(short x,short z)
{
	tilelights[x][z].el.clear();
	float xx=((float)x+0.5f)*ACTIVEBKG->Xdiv;
	float zz=((float)z+0.5f)*ACTIVEBKG->Zdiv;

	for(long i=0; i < TOTPDL; i++) {
		if(closerThan(Vec2f(xx, zz), Vec2f(PDL[i]->pos.x, PDL[i]->pos.z), PDL[i]->fallend + 60.f)) {

			tilelights[x][z].el.push_back(PDL[i]);
		}
	}
}
Пример #9
0
void PrecalcIOLighting(const Vec3f * pos, float radius, long flags)
{
    static Vec3f lastpos;

    if (flags & 1)
    {
        lastpos.x = 99999.f + lastpos.x;
        lastpos.y = 99999.f + lastpos.y;
        lastpos.z = 99999.f + lastpos.z;
        return;
    }

    // Lastpos optim
    if(closerThan(*pos, lastpos, 100.f)) {
        return;
    }

    lastpos.x = pos->x;
    lastpos.y = pos->y;
    lastpos.z = pos->z;

    TOTIOPDL = 0;

    for(size_t i = 0; i < MAX_LIGHTS; i++) {

        EERIE_LIGHT * el = GLight[i];

        if ((el)  && (el->exist) && (el->status)
                && !(el->extras & EXTRAS_SEMIDYNAMIC))
        {
            if ((el->pos.x >= pos->x - radius) && (el->pos.x <= pos->x + radius)
                    && (el->pos.z >= pos->z - radius) && (el->pos.z <= pos->z + radius))
            {

                el->rgb255.r = el->rgb.r * 255.f;
                el->rgb255.g = el->rgb.g * 255.f;
                el->rgb255.b = el->rgb.b * 255.f;
                el->falldiff = el->fallend - el->fallstart;
                el->falldiffmul = 1.f / el->falldiff;
                el->precalc = el->intensity * GLOBAL_LIGHT_FACTOR;
                IO_PDL[TOTIOPDL] = el;

                TOTIOPDL++;

                if ((size_t)TOTIOPDL >= MAX_DYNLIGHTS) TOTIOPDL--;
            }
        }
    }
}
Пример #10
0
void ComputeTileLights(short x, short z) {
	
	tilelights[x][z].el.clear();
	
	Vec2f tileCenter = (Vec2f(x, z) + 0.5f) * g_backgroundTileSize;
	
	for(size_t i = 0; i < g_culledDynamicLightsCount; i++) {
		EERIE_LIGHT * light = g_culledDynamicLights[i];
		
		if(closerThan(tileCenter, Vec2f(light->pos.x, light->pos.z), light->fallend + 60.f)) {

			tilelights[x][z].el.push_back(light);
		}
	}
}
Пример #11
0
void ComputeTileLights(short x,short z)
{
    tilelights[x][z].el.clear();
    float xx=((float)x+0.5f)*ACTIVEBKG->Xdiv;
    float zz=((float)z+0.5f)*ACTIVEBKG->Zdiv;

    for(size_t i = 0; i < TOTPDL; i++) {
        EERIE_LIGHT * light = PDL[i];

        if(closerThan(Vec2f(xx, zz), Vec2f(light->pos.x, light->pos.z), light->fallend + 60.f)) {

            tilelights[x][z].el.push_back(light);
        }
    }
}
Пример #12
0
void EERIEDrawAnimQuatRender(EERIE_3DOBJ *eobj, const Vec3f & pos, Entity *io, float invisibility) {

	ARX_PROFILE_FUNC();
	
	if(io && io != entities.player() && !Cedric_IO_Visible(io->pos))
		return;

	bool isFightingNpc = io &&
						 (io->ioflags & IO_NPC) &&
						 (io->_npcdata->behavior & BEHAVIOUR_FIGHT) &&
						 closerThan(io->pos, player.pos, 240.f);

	if(!isFightingNpc && ARX_SCENE_PORTAL_ClipIO(io, pos))
		return;

	Cedric_AnimateDrawEntityRender(eobj, pos, io, invisibility);
}
Пример #13
0
void PrecalcDynamicLighting(const Vec3f & camPos, float camDepth) {
	
	ARX_PROFILE_FUNC();
	
	g_culledDynamicLightsCount = 0;
	
	BOOST_FOREACH(EERIE_LIGHT & light, g_dynamicLights) {
		if(light.m_exists && light.rgb != Color3f::black) {
			light.m_isVisible = closerThan(light.pos, camPos, camDepth + light.fallend);
			if(light.m_isVisible) {
				RecalcLight(&light);
				arx_assert(g_culledDynamicLightsCount < size_t(boost::size(g_culledDynamicLights)));
				g_culledDynamicLights[g_culledDynamicLightsCount++] = &light;
			}
		}
	}
	
}
Пример #14
0
bool ARX_DAMAGES_TryToDoDamage(const Vec3f & pos, float dmg, float radius, EntityHandle source)
{
	bool ret = false;

	for(size_t i = 0; i < entities.size(); i++) {
		const EntityHandle handle = EntityHandle(i);
		Entity * io = entities[handle];

		if(io != NULL
		   && (entities[handle]->gameFlags & GFLAG_ISINTREATZONE)
		   && io->show == SHOW_FLAG_IN_SCENE
		   && source != handle
		) {
			float threshold;
			float rad = radius + 5.f;

			if(io->ioflags & IO_FIX) {
				threshold = 510;
				rad += 10.f;
			} else if(io->ioflags & IO_NPC) {
				threshold = 250;
			} else {
				threshold = 350;
			}

			if(closerThan(pos, io->pos, threshold) && SphereInIO(io, Sphere(pos, rad))) {
				if(io->ioflags & IO_NPC) {
					if(ValidIONum(source))
						ARX_EQUIPMENT_ComputeDamages(entities[source], io, 1.f);

					ret = true;
				}

				if(io->ioflags & IO_FIX) {
					ARX_DAMAGES_DamageFIX(io, dmg, source, false);
					ret = true;
				}
			}
		}
	}

	return ret;
}
Пример #15
0
//-----------------------------------------------------------------------------
// Updates all currently launched projectiles
void ARX_MISSILES_Update() {
	
	ARX_PROFILE_FUNC();
	
	TextureContainer * tc = TC_fire; 

	unsigned long tim = (unsigned long)(arxtime);

	for(unsigned long i(0); i < MAX_MISSILES; i++) {
		if(missiles[i].type == MISSILE_NONE)
			continue;

		long framediff = missiles[i].timecreation + missiles[i].tolive - tim;

		if(framediff < 0) {
			ARX_MISSILES_Kill(i);
			continue;
		}

		long framediff3 = tim - missiles[i].timecreation;

		switch(missiles[i].type) {
			case MISSILE_NONE:
			break;
			case MISSILE_FIREBALL: {
				Vec3f pos;

				pos = missiles[i].startpos + missiles[i].velocity * Vec3f(framediff3);

				if(lightHandleIsValid(missiles[i].longinfo)) {
					EERIE_LIGHT * light = lightHandleGet(missiles[i].longinfo);
					
					light->pos = pos;
				}

				Vec3f orgn = missiles[i].lastpos;
				Vec3f dest = pos;
				
				Vec3f tro = Vec3f(70.f);
				
				EERIEPOLY *ep = GetMinPoly(dest);
				EERIEPOLY *epp = GetMaxPoly(dest);

				if(closerThan(player.pos, pos, 200.f)) {
					ARX_MISSILES_Kill(i);
					ARX_BOOMS_Add(pos);
					Add3DBoom(pos);
					DoSphericDamage(Sphere(dest, 200.0F), 180.0F, DAMAGE_AREAHALF, DAMAGE_TYPE_FIRE | DAMAGE_TYPE_MAGICAL);
					break;
				}

				if(ep && ep->center.y < dest.y) {
					ARX_MISSILES_Kill(i);
					ARX_BOOMS_Add(dest);
					Add3DBoom(dest);
					DoSphericDamage(Sphere(dest, 200.0F), 180.0F, DAMAGE_AREAHALF, DAMAGE_TYPE_FIRE | DAMAGE_TYPE_MAGICAL);
					break;
				}

				if(epp && epp->center.y > dest.y) {
					ARX_MISSILES_Kill(i);
					ARX_BOOMS_Add(dest);
					Add3DBoom(dest);
					DoSphericDamage(Sphere(dest, 200.0F), 180.0F, DAMAGE_AREAHALF, DAMAGE_TYPE_FIRE | DAMAGE_TYPE_MAGICAL);
					break;
				}

				Vec3f hit;
				if(EERIELaunchRay3(orgn, dest, hit, 1)) {
					ARX_MISSILES_Kill(i);
					ARX_BOOMS_Add(hit);
					Add3DBoom(hit);
					DoSphericDamage(Sphere(dest, 200.0F), 180.0F, DAMAGE_AREAHALF, DAMAGE_TYPE_FIRE | DAMAGE_TYPE_MAGICAL);
					break;
				}

				if(!CheckInPoly(dest) || EEIsUnderWater(dest)) {
					ARX_MISSILES_Kill(i);
					ARX_BOOMS_Add(dest);
					Add3DBoom(dest);
					DoSphericDamage(Sphere(dest, 200.0F), 180.0F, DAMAGE_AREAHALF, DAMAGE_TYPE_FIRE | DAMAGE_TYPE_MAGICAL);
					break;
				}

				EntityHandle ici = IsCollidingAnyInter(dest, tro);

				if(ici != EntityHandle() && ici != missiles[i].owner) {
					ARX_MISSILES_Kill(i);
					ARX_BOOMS_Add(dest);
					Add3DBoom(dest);
					DoSphericDamage(Sphere(dest, 200.0F), 180.0F, DAMAGE_AREAHALF, DAMAGE_TYPE_FIRE | DAMAGE_TYPE_MAGICAL);
					break;
				}
				
				PARTICLE_DEF * pd = createParticle();
				if(pd) {
					pd->ov = pos;
					pd->move = missiles[i].velocity;
					pd->move += Vec3f(3.f, 4.f, 3.f) + Vec3f(-6.f, -12.f, -6.f) * randomVec3f();
					pd->tolive = Random::get(500, 1000);
					pd->tc = tc;
					pd->siz = 12.f * float(missiles[i].tolive - framediff3) * (1.f / 4000);
					pd->scale = randomVec(15.f, 20.f);
					pd->special = FIRE_TO_SMOKE;
				}
				
				missiles[i].lastpos = pos;
				
				break;
			}
		}

		missiles[i].lastupdate = tim;
	}
}
Пример #16
0
void IgnitSpell::Launch()
{
	m_duration = 500;
	
	if(m_hand_group != -1) {
		m_srcPos = m_hand_pos;
	} else {
		m_srcPos = m_caster_pos - Vec3f(0.f, 50.f, 0.f);
	}
	
	LightHandle id = GetFreeDynLight();
	if(lightHandleIsValid(id)) {
		EERIE_LIGHT * light = lightHandleGet(id);
		
		light->intensity = 1.8f;
		light->fallend   = 450.f;
		light->fallstart = 380.f;
		light->rgb       = Color3f(1.f, 0.75f, 0.5f);
		light->pos       = m_srcPos;
		light->duration  = 300;
	}
	
	float fPerimeter = 400.f + m_level * 30.f;
	
	m_lights.clear();
	m_elapsed = 0;
	
	CheckForIgnition(m_srcPos, fPerimeter, 1, 1);
	
	for(size_t ii = 0; ii < MAX_LIGHTS; ii++) {
		EERIE_LIGHT * light = GLight[ii];
		
		if(!light || !(light->extras & EXTRAS_EXTINGUISHABLE)) {
			continue;
		}
		
		if(m_caster == PlayerEntityHandle && (light->extras & EXTRAS_NO_IGNIT)) {
			continue;
		}
		
		if(!(light->extras & EXTRAS_SEMIDYNAMIC)
		  && !(light->extras & EXTRAS_SPAWNFIRE)
		  && !(light->extras & EXTRAS_SPAWNSMOKE)) {
			continue;
		}
		
		if(light->m_ignitionStatus) {
			continue;
		}
		
		if(!fartherThan(m_srcPos, light->pos, fPerimeter)) {
			
			T_LINKLIGHTTOFX entry;
			
			entry.iLightNum = ii;
			entry.poslight = light->pos;
		
			entry.idl = GetFreeDynLight();
		
			if(lightHandleIsValid(entry.idl)) {
				EERIE_LIGHT * light = lightHandleGet(entry.idl);
				
				light->intensity = 0.7f + 2.f * rnd();
				light->fallend = 400.f;
				light->fallstart = 300.f;
				light->rgb = Color3f(1.f, 1.f, 1.f);
				light->pos = entry.poslight;
			}
		
			m_lights.push_back(entry);
		}
	}
	
	for(size_t n = 0; n < MAX_SPELLS; n++) {
		SpellBase * spell = spells[SpellHandle(n)];
		
		if(!spell) {
			continue;
		}
		if(spell->m_type == SPELL_FIREBALL) {
			CSpellFx * pCSpellFX = spell->m_pSpellFx;
			if(pCSpellFX) {
				CFireBall * pCF = (CFireBall *)pCSpellFX;
				float radius = std::max(m_level * 2.f, 12.f);
				if(closerThan(m_srcPos, pCF->eCurPos,
				              fPerimeter + radius)) {
					spell->m_level += 1;
				}
			}
		}
	}
}
Пример #17
0
//-----------------------------------------------------------------------------
// Updates all currently launched projectiles
void ARX_MISSILES_Update()
{
	long framediff, framediff3;
	Vec3f orgn, dest, hit;
	TextureContainer * tc = TC_fire; 
	EERIEPOLY *tp = NULL;
	unsigned long tim = ARXTimeUL();

	for (unsigned long i(0); i < MAX_MISSILES; i++) 
	{
		if (missiles[i].type == MISSILE_NONE) continue;

		framediff = missiles[i].timecreation + missiles[i].tolive - tim;

		if (framediff < 0)
		{
			ARX_MISSILES_Kill(i);
			continue;
		}

		framediff3 = tim - missiles[i].timecreation;

		switch (missiles[i].type)
		{
			case MISSILE_NONE: break;
			case MISSILE_FIREBALL: {
				Vec3f pos;

				pos = missiles[i].startpos + missiles[i].velocity * framediff3;

				if (missiles[i].longinfo != -1)
				{
					DynLight[missiles[i].longinfo].pos = pos;
				}

#ifdef BUILD_EDITOR
				if (USE_COLLISIONS)
#endif
				{
					orgn = missiles[i].lastpos;
					dest = pos;
					
					EERIEPOLY *ep;
					EERIEPOLY *epp;
					Vec3f tro;
					tro.x = 70.0F;
					tro.y = 70.0F;
					tro.z = 70.0F;

					CURRENTINTER = NULL;
					ep = GetMinPoly(dest.x, dest.y, dest.z);
					epp = GetMaxPoly(dest.x, dest.y, dest.z);

					if(closerThan(player.pos, pos, 200.f)) {
						ARX_MISSILES_Kill(i);
						ARX_BOOMS_Add(&pos);
						Add3DBoom(&pos);
						DoSphericDamage(&dest, 180.0F, 200.0F, DAMAGE_AREAHALF, DAMAGE_TYPE_FIRE | DAMAGE_TYPE_MAGICAL);
						break;
					}

					if (ep  && ep->center.y < dest.y)
					{
						ARX_MISSILES_Kill(i);
						ARX_BOOMS_Add(&dest);
						Add3DBoom(&dest);
						DoSphericDamage(&dest, 180.0F, 200.0F, DAMAGE_AREAHALF, DAMAGE_TYPE_FIRE | DAMAGE_TYPE_MAGICAL);
						break;
					}

					if (epp && epp->center.y > dest.y)
					{
						ARX_MISSILES_Kill(i);
						ARX_BOOMS_Add(&dest);
						Add3DBoom(&dest);
						DoSphericDamage(&dest, 180.0F, 200.0F, DAMAGE_AREAHALF, DAMAGE_TYPE_FIRE | DAMAGE_TYPE_MAGICAL);
						break;
					}

					if (EERIELaunchRay3(&orgn, &dest, &hit, tp, 1))
					{
						ARX_MISSILES_Kill(i);
						ARX_BOOMS_Add(&hit);
						Add3DBoom(&hit);
						DoSphericDamage(&dest, 180.0F, 200.0F, DAMAGE_AREAHALF, DAMAGE_TYPE_FIRE | DAMAGE_TYPE_MAGICAL);
						break;
					}

					if ( !EECheckInPoly(&dest) || EEIsUnderWater(&dest) )
					{
						ARX_MISSILES_Kill(i);
						ARX_BOOMS_Add(&dest);
						Add3DBoom(&dest);
						DoSphericDamage(&dest, 180.0F, 200.0F, DAMAGE_AREAHALF, DAMAGE_TYPE_FIRE | DAMAGE_TYPE_MAGICAL);
						break;
					}

					long ici = IsCollidingAnyInter(dest.x, dest.y, dest.z, &tro);

					if (ici != -1 && ici != missiles[i].owner)
					{
						ARX_MISSILES_Kill(i);
						ARX_BOOMS_Add(&dest);
						Add3DBoom(&dest);
						DoSphericDamage(&dest, 180.0F, 200.0F, DAMAGE_AREAHALF, DAMAGE_TYPE_FIRE | DAMAGE_TYPE_MAGICAL);
						break;
					}
				}

				long j = ARX_PARTICLES_GetFree();

				if (j != -1 && !ARXPausedTimer)
				{
					ParticleCount++;
					particle[j].exist = true;
					particle[j].zdec = 0;
					particle[j].ov.x = pos.x;
					particle[j].ov.y = pos.y;
					particle[j].ov.z = pos.z;
					particle[j].move.x = missiles[i].velocity.x + 3.0f - 6.0F * rnd();
					particle[j].move.y = missiles[i].velocity.y + 4.0F - 12.0F * rnd();
					particle[j].move.z = missiles[i].velocity.z + 3.0F - 6.0F * rnd();
					particle[j].timcreation = tim;
					particle[j].tolive = 500 + (unsigned long)(rnd() * 500.f);
					particle[j].tc = tc;
					particle[j].siz = 12.0F * (float)(missiles[i].tolive - framediff3) * ( 1.0f / 4000 );
					particle[j].scale.x = 15.0F + rnd() * 5.0F;
					particle[j].scale.y = 15.0F + rnd() * 5.0F;
					particle[j].scale.z = 15.0F + rnd() * 5.0F;
					particle[j].special = FIRE_TO_SMOKE;
				}

				missiles[i].lastpos.x = pos.x;
				missiles[i].lastpos.y = pos.y;
				missiles[i].lastpos.z = pos.z;

				break;
			}
		}

		missiles[i].lastupdate = tim;
	}
}
Пример #18
0
void DouseSpell::Launch()
{
	m_duration = 500;
	
	Vec3f target;
	if(m_hand_group >= 0) {
		target = m_hand_pos;
	} else {
		target = m_caster_pos;
		target.y -= 50.f;
	}
	
	float fPerimeter = 400.f + m_level * 30.f;
	
	CheckForIgnition(target, fPerimeter, 0, 1);
	
	for(size_t ii = 0; ii < MAX_LIGHTS; ii++) {
		EERIE_LIGHT * light = GLight[ii];
		
		if(!light || !(light->extras & EXTRAS_EXTINGUISHABLE)) {
			continue;
		}
		
		if(!(light->extras & EXTRAS_SEMIDYNAMIC)
		  && !(light->extras & EXTRAS_SPAWNFIRE)
		  && !(light->extras & EXTRAS_SPAWNSMOKE)) {
			continue;
		}
		
		if(!light->m_ignitionStatus) {
			continue;
		}
		
		if(!fartherThan(target, light->pos, fPerimeter)) {
			T_LINKLIGHTTOFX entry;
			
			entry.iLightNum = ii;
			entry.poslight = light->pos;
			m_lights.push_back(entry);
		}
	}
	
	if(player.torch && closerThan(target, player.pos, fPerimeter)) {
		ARX_PLAYER_ClickedOnTorch(player.torch);
	}
	
	for(size_t k = 0; k < MAX_SPELLS; k++) {
		SpellBase * spell = spells[SpellHandle(k)];
		
		if(!spell) {
			continue;
		}
		
		switch(spell->m_type) {
			
			case SPELL_FIREBALL: {
				CSpellFx * pCSpellFX = spell->m_pSpellFx;
				if(pCSpellFX) {
					CFireBall * pCF = (CFireBall *)pCSpellFX;
					float radius = std::max(m_level * 2.f, 12.f);
					if(closerThan(target, pCF->eCurPos,
					              fPerimeter + radius)) {
						spell->m_level -= m_level;
						if(spell->m_level < 1) {
							spells.endSpell(spell);
						}
					}
				}
				break;
			}
			
			case SPELL_FIRE_FIELD: {
				Vec3f pos;
				if(GetSpellPosition(&pos, spell)) {
					if(closerThan(target, pos, fPerimeter + 200)) {
						spell->m_level -= m_level;
						if(spell->m_level < 1) {
							spells.endSpell(spell);
						}
					}
				}
				break;
			}
			
			default: break;
		}
	}
}
Пример #19
0
bool Manage3DCursor(Entity * io, bool simulate) {
	
	arx_assert(io);
	
	if(BLOCK_PLAYER_CONTROLS)
		return false;

	float ag = player.angle.getYaw();

	if(ag > 180)
		ag = ag - 360;

	float drop_miny = (float)(g_size.center().y) - g_size.center().y * (ag * (1.f/70));

	if(DANAEMouse.y < drop_miny)
		return false;
	
	Anglef temp = Anglef::ZERO;

	if(io->ioflags & IO_INVERTED) {
		temp.setYaw(180.f);
		temp.setPitch(-MAKEANGLE(270.f - io->angle.getPitch() - (player.angle.getPitch() - STARTED_ANGLE)));
	} else {
		temp.setPitch(MAKEANGLE(270.f - io->angle.getPitch() - (player.angle.getPitch() - STARTED_ANGLE)));
	}
	
	EERIE_3D_BBOX bbox;
	for(size_t i = 0; i < io->obj->vertexlist.size(); i++) {
		bbox.add(io->obj->vertexlist[i].v);
	}
	
	Vec3f mvectx = angleToVectorXZ(player.angle.getPitch() - 90.f);
	
	Vec2f mod = Vec2f(Vec2i(DANAEMouse) - g_size.center()) / Vec2f(g_size.center()) * Vec2f(160.f, 220.f);
	mvectx *= mod.x;
	Vec3f mvecty(0, mod.y, 0);

	Vec3f orgn = player.pos;
	orgn += angleToVector(player.angle) * 50.f;
	orgn += mvectx;
	orgn.y += mvecty.y;

	Vec3f dest = player.pos;
	dest += angleToVector(player.angle) * 10000.f;
	dest += mvectx;
	dest.y += mvecty.y * 5.f;
	
	Vec3f pos = orgn;

	Vec3f movev = glm::normalize(dest - orgn);

	float lastanything = 0.f;
	float height = -(bbox.max.y - bbox.min.y);

	if(height > -30.f)
		height = -30.f;
	
	Vec3f objcenter = bbox.min + (bbox.max - bbox.min) * Vec3f(0.5f);
	
	Vec3f collidpos = Vec3f_ZERO;
	bool collidpos_ok = false;
	
	{
	float maxdist = 0.f;
	
	for(size_t i = 0; i < io->obj->vertexlist.size(); i++) {
		const EERIE_VERTEX & vert = io->obj->vertexlist[i];
		
		float dist = glm::distance(Vec2f(objcenter.x, objcenter.z), Vec2f(vert.v.x, vert.v.z)) - 4.f;
		maxdist = std::max(maxdist, dist);
	}

	if(io->obj->pbox) {
		Vec2f tmpVert(io->obj->pbox->vert[0].initpos.x, io->obj->pbox->vert[0].initpos.z);
		
		for(int i = 1; i < io->obj->pbox->nb_physvert; i++) {
			const PHYSVERT & physVert = io->obj->pbox->vert[i];
			
			float dist = glm::distance(tmpVert, Vec2f(physVert.initpos.x, physVert.initpos.z)) + 14.f;
			maxdist = std::max(maxdist, dist);
		}
	}
	
	Cylinder cyl2;
	const float inc = 10.f;
	long iterating = 40;

	cyl2.height = std::min(-30.f, height);
	cyl2.radius = glm::clamp(maxdist, 20.f, 150.f);
	
	while(iterating > 0) {
		cyl2.origin = pos + movev * inc + Vec3f(0.f, bbox.max.y, 0.f);

		float anything = CheckAnythingInCylinder(cyl2, io, CFLAG_JUST_TEST | CFLAG_COLLIDE_NOCOL | CFLAG_NO_NPC_COLLIDE);

		if(anything < 0.f) {
			if(iterating == 40) {
				CANNOT_PUT_IT_HERE = 1;
				// TODO is this correct ?
				return true;
			}

			iterating = 0;

			collidpos = cyl2.origin;

			if(lastanything < 0.f) {
				pos.y += lastanything;
				collidpos.y += lastanything;
			}
		} else {
			pos = cyl2.origin;
			lastanything = anything;
		}

		iterating--;
	}
	collidpos_ok = iterating == -1;
	
	}
	
	objcenter = VRotateY(objcenter, temp.getPitch());
	
	collidpos.x -= objcenter.x;
	collidpos.z -= objcenter.z;

	pos.x -= objcenter.x;
	pos.z -= objcenter.z;

	if(!collidpos_ok) {
		CANNOT_PUT_IT_HERE = 1;
		return false;
	}

	if(collidpos_ok && closerThan(player.pos, pos, 300.f)) {
		if(simulate) {
			ARX_INTERACTIVE_Teleport(io, pos, true);

			io->gameFlags &= ~GFLAG_NOCOMPUTATION;
			
			glm::quat rotation = glm::toQuat(toRotationMatrix(temp));
			
			if(SPECIAL_DRAGINTER_RENDER) {
			if(glm::abs(lastanything) > glm::abs(height)) {
				TransformInfo t(collidpos, rotation, io->scale);

				static const float invisibility = 0.5f;

				DrawEERIEInter(io->obj, t, io, false, invisibility);
			} else {
				TransformInfo t(pos, rotation, io->scale);

				float invisibility = Cedric_GetInvisibility(io);

				DrawEERIEInter(io->obj, t, io, false, invisibility);
			}
			}
		} else {
			if(glm::abs(lastanything) > std::min(glm::abs(height), 12.0f)) {
				Entity * io = DRAGINTER;
				ARX_PLAYER_Remove_Invisibility();
				io->obj->pbox->active = 1;
				io->obj->pbox->stopcount = 0;
				io->pos = collidpos;
				io->velocity = Vec3f_ZERO;

				io->stopped = 1;

				movev.x *= 0.0001f;
				movev.y = 0.1f;
				movev.z *= 0.0001f;
				Vec3f viewvector = movev;

				Anglef angle = temp;
				io->soundtime = 0;
				io->soundcount = 0;
				EERIE_PHYSICS_BOX_Launch(io->obj, io->pos, angle, viewvector);
				ARX_SOUND_PlaySFX(SND_WHOOSH, &pos);
				io->show = SHOW_FLAG_IN_SCENE;
				Set_DragInter(NULL);
			} else {
				ARX_PLAYER_Remove_Invisibility();
				ARX_SOUND_PlayInterface(SND_INVSTD);
				ARX_INTERACTIVE_Teleport(io, pos, true);

				io->angle.setYaw(temp.getYaw());
				io->angle.setPitch(270.f - temp.getPitch());
				io->angle.setRoll(temp.getRoll());

				io->stopped = 0;
				io->show = SHOW_FLAG_IN_SCENE;
				io->obj->pbox->active = 0;
				Set_DragInter(NULL);
			}
		}

		GRenderer->SetCulling(Renderer::CullNone);
		return true;
	} else {
		CANNOT_PUT_IT_HERE=-1;
	}

	return false;
}
void ControlTargetSpell::Launch()
{
	// TODO copy-paste
	for(size_t ii = 1; ii < entities.size(); ii++) {
		const EntityHandle handle = EntityHandle(ii);
		Entity * ioo = entities[handle];
		
		if(!ioo || !(ioo->ioflags & IO_NPC)) {
			continue;
		}
		
		if(ioo->_npcdata->lifePool.current <= 0.f || ioo->show != SHOW_FLAG_IN_SCENE) {
			continue;
		}
		
		if(ioo->groups.find("demon") == ioo->groups.end()) {
			continue;
		}
		
		if(closerThan(ioo->pos, m_caster_pos, 900.f)) {
			std::ostringstream oss;
			oss << entities[m_target]->idString();
			oss << ' ' << long(m_level);
			SendIOScriptEvent(ioo, SM_NULL, oss.str(), "npc_control");
		}
	}
	
	ARX_SOUND_PlaySFX(SND_SPELL_CONTROL_TARGET);
	
	m_duration = 1000;
	
	eSrc = Vec3f_ZERO;
	eTarget = Vec3f_ZERO;
	fTrail = 0.f;
	
	tex_mm = TextureContainer::Load("graph/obj3d/textures/(fx)_ctrl_target");
	
	eSrc = player.pos;
	
	float fBetaRad = glm::radians(player.angle.getPitch());
	float fBetaRadCos = glm::cos(fBetaRad);
	float fBetaRadSin = glm::sin(fBetaRad);
	
	eTarget = eSrc + Vec3f(-fBetaRadSin * 1000.f, 100.f, fBetaRadCos * 1000.f);
	
	for(size_t i = 1; i < entities.size(); i++) {
		const EntityHandle handle = EntityHandle(i);
		Entity * e = entities[handle];
		
		if(e) {
			eTarget = e->pos;
		}
	}
	
	Vec3f h;
	Vec3f s = eSrc;
	Vec3f e = eSrc;
	int i = 0;
	while(Visible(s, e, &h) && i < 20) {
		e.x -= fBetaRadSin * 50;
		e.z += fBetaRadCos * 50;
		i++;
	}
	
	pathways[0] = eSrc + Vec3f(0.f, 100.f, 0.f);
	pathways[9] = eTarget;
	Split(pathways, 0, 9, 150);
	
	for(int i = 0; i < 9; i++) {
		if(pathways[i].y >= eSrc.y + 150) {
			pathways[i].y = eSrc.y + 150;
		}
	}
	
	fTrail = 0;
}
Пример #21
0
void DispellFieldSpell::Launch()
{
	m_duration = 10;
	
	long valid = 0, dispelled = 0;

	for(size_t n = 0; n < MAX_SPELLS; n++) {
		SpellBase * spell = spells[SpellHandle(n)];
		
		if(!spell) {
			continue;
		}
		
		bool cancel = false;
		Vec3f pos;
		
		switch(spell->m_type) {
			
			case SPELL_CREATE_FIELD: {
				if(m_caster != PlayerEntityHandle || spell->m_caster == PlayerEntityHandle) {
					pos = static_cast<CreateFieldSpell *>(spell)->getPosition();
					cancel = true;
				}
				break;
			}
			
			case SPELL_FIRE_FIELD: {
				pos = static_cast<FireFieldSpell *>(spell)->getPosition();
				cancel = true;
				break;
			}
			
			case SPELL_ICE_FIELD: {
				pos = static_cast<IceFieldSpell *>(spell)->getPosition();
				cancel = true;
				break;
			}
			
			default: break;
		}
		
		Entity * caster = entities[m_caster];
		if(cancel && closerThan(pos, caster->pos, 400.f)) {
			valid++;
			if(spell->m_level <= m_level) {
				spells.endSpell(spell);
				dispelled++;
			}
		}
	}
	
	if(valid > dispelled) {
		// Some fileds could not be dispelled
		ARX_SPEECH_AddSpeech(entities.player(), "player_not_skilled_enough",
		                     ANIM_TALK_NEUTRAL, ARX_SPEECH_FLAG_NOTEXT);
	}
	
	if(dispelled > 0) {
		ARX_SOUND_PlaySFX(SND_SPELL_DISPELL_FIELD);
	} else {
		ARX_SOUND_PlaySFX(SND_MAGIC_FIZZLE, &m_caster_pos);
	}
}
Пример #22
0
void IgnitSpell::Launch()
{
	m_duration = ArxDurationMs(500);
	
	if(m_hand_group != ActionPoint()) {
		m_srcPos = m_hand_pos;
	} else {
		m_srcPos = m_caster_pos - Vec3f(0.f, 50.f, 0.f);
	}
	
	EERIE_LIGHT * light = dynLightCreate();
	if(light) {
		light->intensity = 1.8f;
		light->fallend   = 450.f;
		light->fallstart = 380.f;
		light->rgb       = Color3f(1.f, 0.75f, 0.5f);
		light->pos       = m_srcPos;
		light->duration  = ArxDurationMs(300);
	}
	
	float fPerimeter = 400.f + m_level * 30.f;
	
	m_lights.clear();
	m_elapsed = ArxDuration_ZERO;
	
	CheckForIgnition(Sphere(m_srcPos, fPerimeter), 1, 1);
	
	for(size_t ii = 0; ii < g_staticLightsMax; ii++) {
		EERIE_LIGHT * light = g_staticLights[ii];
		
		if(!light || !(light->extras & EXTRAS_EXTINGUISHABLE)) {
			continue;
		}
		
		if(m_caster == EntityHandle_Player && (light->extras & EXTRAS_NO_IGNIT)) {
			continue;
		}
		
		if(!(light->extras & EXTRAS_SEMIDYNAMIC)
		  && !(light->extras & EXTRAS_SPAWNFIRE)
		  && !(light->extras & EXTRAS_SPAWNSMOKE)) {
			continue;
		}
		
		if(light->m_ignitionStatus) {
			continue;
		}
		
		if(!fartherThan(m_srcPos, light->pos, fPerimeter)) {
			
			T_LINKLIGHTTOFX entry;
			
			entry.m_targetLight = ii;
			
			EERIE_LIGHT * light = dynLightCreate(entry.m_effectLight);
			if(light) {
				light->intensity = Random::getf(0.7f, 2.7f);
				light->fallend = 400.f;
				light->fallstart = 300.f;
				light->rgb = Color3f(1.f, 1.f, 1.f);
				light->pos = light->pos;
			}
		
			m_lights.push_back(entry);
		}
	}
	
	for(size_t n = 0; n < MAX_SPELLS; n++) {
		SpellBase * spell = spells[SpellHandle(n)];
		
		if(!spell) {
			continue;
		}
		if(spell->m_type == SPELL_FIREBALL) {
			Vec3f pos = static_cast<FireballSpell *>(spell)->getPosition();
			
			float radius = std::max(m_level * 2.f, 12.f);
			if(closerThan(m_srcPos, pos, fPerimeter + radius)) {
				spell->m_level += 1;
			}
		}
	}
}
Пример #23
0
void DouseSpell::Launch()
{
	m_duration = ArxDurationMs(500);
	
	Vec3f target;
	if(m_hand_group != ActionPoint()) {
		target = m_hand_pos;
	} else {
		target = m_caster_pos;
		target.y -= 50.f;
	}
	
	float fPerimeter = 400.f + m_level * 30.f;
	
	CheckForIgnition(Sphere(target, fPerimeter), 0, 1);
	
	for(size_t ii = 0; ii < g_staticLightsMax; ii++) {
		EERIE_LIGHT * light = g_staticLights[ii];
		
		if(!light || !(light->extras & EXTRAS_EXTINGUISHABLE)) {
			continue;
		}
		
		if(!(light->extras & EXTRAS_SEMIDYNAMIC)
		  && !(light->extras & EXTRAS_SPAWNFIRE)
		  && !(light->extras & EXTRAS_SPAWNSMOKE)) {
			continue;
		}
		
		if(!light->m_ignitionStatus) {
			continue;
		}
		
		if(!fartherThan(target, light->pos, fPerimeter)) {
			m_lights.push_back(ii);
		}
	}
	
	if(player.torch && closerThan(target, player.pos, fPerimeter)) {
		ARX_PLAYER_ClickedOnTorch(player.torch);
	}
	
	for(size_t k = 0; k < MAX_SPELLS; k++) {
		SpellBase * spell = spells[SpellHandle(k)];
		
		if(!spell) {
			continue;
		}
		
		switch(spell->m_type) {
			
			case SPELL_FIREBALL: {
				Vec3f pos = spell->getPosition();
				float radius = std::max(m_level * 2.f, 12.f);
				if(closerThan(target, pos, fPerimeter + radius)) {
					spell->m_level -= m_level;
					if(spell->m_level < 1) {
						spells.endSpell(spell);
					}
				}
				break;
			}
			
			case SPELL_FIRE_FIELD: {
				Vec3f pos = spell->getPosition();
				if(closerThan(target, pos, fPerimeter + 200)) {
					spell->m_level -= m_level;
					if(spell->m_level < 1) {
						spells.endSpell(spell);
					}
				}
				break;
			}
			
			default: break;
		}
	}
}
Пример #24
0
static void drawDebugPaths() {
	
	GRenderer->SetRenderState(Renderer::DepthTest, false);
	
	for(long i = 0; i < nbARXpaths; i++) {
		
		ARX_PATH * path = ARXpaths[i];
		if(!path) {
			continue;
		}
		
		Vec3f center = Vec3f_ZERO;
		int n = 0;
		
		std::vector<Vec3f> points;
		for(long i = 0; i < path->nb_pathways; i++) {
			const ARX_PATHWAY & node = path->pathways[i];
			Vec3f pos = path->pos + node.rpos;
			points.push_back(pos);
			center += pos, n++;
			if(node.flag == PATHWAY_BEZIER) {
				// Interpolate bezier curve by creating linear segments
				if(i + 2 >= path->nb_pathways) {
					break;
				}
				const size_t nsegments = 20;
				for(size_t j = 0; j < nsegments; j++) {
					points.push_back(path->interpolateCurve(i, float(j) / nsegments));
				}
				i++; // Skip the control point
			}
		}
		
		// Zones only check the bounding box for the y coordinate - adjust display for that
		if(path->height > 0) {
			for(size_t i = 0; i < points.size(); i++) {
				points[i].y = path->bbmin.y;
			}
		}
		
		if(path->height != 0 || ((path->flags & PATH_LOOP) && points.size() > 0)) {
			points.push_back(points[0]);
		}
		
		Color color = (path->height != 0) ? Color::green : Color::red;
		
		for(size_t i = 0; i + 1 < points.size(); i++) {
			drawLine(points[i], points[i + 1], color);
		}
		
		if(path->height > 0) {
			Vec3f offset(0.f, (path->bbmax.y - path->bbmin.y), 0.f);
			for(size_t i = 0; i + 1 < points.size(); i++) {
				drawLine(points[i] + offset, points[i + 1] + offset, color);
			}
			for(size_t i = 0; i < points.size(); i++) {
				drawLine(points[i], points[i] + offset, color);
			}
		}
		
		// Display the name and controlling entity for close zones
		if(!path->name.empty() || !path->controled.empty()) {
			if(path->height > 0) {
				center = (path->bbmin + path->bbmax) / 2.f;
			} else if(n != 0) {
				center /= float(n);
			} else {
				center = path->pos;
			}
			if(closerThan(center, player.pos, DebugTextMaxDistance)) {
				std::string controlledby;
				if(!path->controled.empty()) {
					controlledby = "Controlled by: " + path->controled;
				}
				Color textcolor = color * 0.5f + Color::gray(0.5f);
				drawTextAt(hFontDebug, center, path->name, textcolor, controlledby);
			}
		}
		
	}
	
	GRenderer->SetRenderState(Renderer::DepthTest, true);
	
}
Пример #25
0
static void drawDebugPathFinding() {
	
	if(!ACTIVEBKG || !ACTIVEBKG->anchors) {
		return;
	}
	
	const float zbias = 0.00001f;
	
	for(long i = 0; i < ACTIVEBKG->nbanchors; i++) {
		
		const ANCHOR_DATA & node = ACTIVEBKG->anchors[i];
		
		Color color1 = (node.flags & ANCHOR_FLAG_BLOCKED) ? Color::blue : Color::green;
		for(long j = 0; j < node.nblinked; j++) {
			long k = node.linked[j];
			if(k >= 0 && k < ACTIVEBKG->nbanchors && i < k) {
				const ANCHOR_DATA & other = ACTIVEBKG->anchors[k];
				Color color2 = (other.flags & ANCHOR_FLAG_BLOCKED) ? Color::blue : Color::green;
				drawLine(node.pos, other.pos, color1, color2, zbias);
			}
		}
		
		if(node.height != 0.f) {
			Vec3f toppos = node.pos + Vec3f(0.f, node.height, 0.f);
			drawLine(node.pos, toppos, Color::blue, zbias);
		}
		
	}
	
	// Highlight active paths
	for(size_t i = 1; i < entities.size(); i++) {
		const EntityHandle handle = EntityHandle(i);
		const Entity * entity = entities[handle];
		
		if(!entity || !(entity->ioflags & IO_NPC)) {
			continue;
		}
		const IO_PATHFIND & pathfind = entity->_npcdata->pathfind;
		if(pathfind.listnb <= 0 || !pathfind.list) {
			continue;
		}
		
		// Draw visited nodes yellow and target nodes as red
		for(long j = 1; j < pathfind.listnb; j++) {
			short k0 = pathfind.list[j - 1], k1 = pathfind.list[j];
			if(k0 >= 0 && k0 < ACTIVEBKG->nbanchors && k1 >= 0 && k1 < ACTIVEBKG->nbanchors) {
				const ANCHOR_DATA & n0 = ACTIVEBKG->anchors[k0], & n1 = ACTIVEBKG->anchors[k1];
				Color color0 = (j     <= pathfind.listpos) ? Color::yellow : Color::red;
				Color color1 = (j + 1 <= pathfind.listpos) ? Color::yellow : Color::red;
				drawLine(n0.pos, n1.pos, color0, color1, 2.f * zbias);
			}
		}
		
		// Highlight end nodes
		short k0 = pathfind.list[pathfind.listnb - 1];
		if(k0 >= 0 && k0 < ACTIVEBKG->nbanchors) {
			Anglef angle(0.f, 0.f, 0.f);
			Vec3f scale(0.5f);
			RenderMaterial mat;
			mat.setBlendType(RenderMaterial::Opaque);
			mat.setDepthTest(true);
			
			Draw3DObject(g_nodeObject, angle, ACTIVEBKG->anchors[k0].pos, scale, Color3f::white, mat);
		}
		
		// Show entity ID at the active node
		if(pathfind.listpos < pathfind.listnb) {
			short k1 = pathfind.list[pathfind.listpos];
			if(k1 >= 0 && k1 < ACTIVEBKG->nbanchors) {
				if(closerThan(ACTIVEBKG->anchors[k1].pos, player.pos, DebugTextMaxDistance)) {
					drawTextAt(hFontDebug, ACTIVEBKG->anchors[k1].pos, entity->idString());
					GRenderer->SetRenderState(Renderer::DepthTest, true);
				}
			}
		}
		
	}
	
}
Пример #26
0
// Converts a Theo Object to an EERIE object
static EERIE_3DOBJ * TheoToEerie(const char * adr, long size, const res::path & texpath, const res::path & fic) {
	
	LogWarning << "TheoToEerie " << fic;
	
	if(!adr)
		return NULL;
	
	res::path txpath = texpath.empty() ? "graph/obj3d/textures" : texpath;
	
	if(size < 10) {
		return NULL;
	}
	
	size_t pos = 0;
	
	const THEO_HEADER * pth = reinterpret_cast<const THEO_HEADER *>(adr + pos);
	pos += sizeof(THEO_HEADER);
	
	if(pth->version < 3003 || pth->version > 3011) {
		LogError << "TheoToEerie: invalid version in " << fic << ": found " << pth->version
		         << " expected 3004 to 3011";
		return NULL;
	}
	
	EERIE_3DOBJ * eerie = new EERIE_3DOBJ;
	eerie->clear();
	
	eerie->file = fic;
	
	if(pth->type_write == 0) {
		// read the texture
		
		LogError <<  "WARNING object " << fic << " SAVE MAP IN OBJECT = INVALID... Using Dummy Textures...";
		
		eerie->texturecontainer.resize(pth->nb_maps);
		for(long i = 0; i < pth->nb_maps; i++) {
			pos += sizeof(THEO_TEXTURE);
			eerie->texturecontainer[i] = GetAnyTexture();
		}
		
	} else {
		
		if((pth->type_write & SAVE_MAP_BMP) || (pth->type_write & SAVE_MAP_TGA)) {
			
			eerie->texturecontainer.resize(pth->nb_maps);
			for(long i = 0; i < pth->nb_maps; i++) {
				
				res::path name;
				if(pth->version >= 3008) {
					const THEO_SAVE_MAPS_IN_3019 * tsmi3019 = reinterpret_cast<const THEO_SAVE_MAPS_IN_3019 *>(adr + pos);
					pos += sizeof(THEO_SAVE_MAPS_IN_3019);
					name = res::path::load(util::loadString(tsmi3019->texture_name)).remove_ext();
				} else {
					const THEO_SAVE_MAPS_IN * tsmi = reinterpret_cast<const THEO_SAVE_MAPS_IN *>(adr + pos);
					pos += sizeof(THEO_SAVE_MAPS_IN);
					name = res::path::load(util::loadString(tsmi->texture_name)).remove_ext();
				}
				
				if(!name.empty()) {
					eerie->texturecontainer[i] = TextureContainer::Load(txpath / name, TextureContainer::Level);
				}
			}
		}
	}
	
	pos = pth->object_seek;
	loadObjectData(eerie, adr, &pos, pth->version);
	eerie->angle = Anglef::ZERO;
	eerie->pos = Vec3f_ZERO;

	// NORMALS CALCULATIONS

	//Compute Faces Areas
	for(size_t i = 0; i < eerie->facelist.size(); i++) {
		const Vec3f & p0 = eerie->vertexlist[eerie->facelist[i].vid[0]].v;
		const Vec3f & p1 = eerie->vertexlist[eerie->facelist[i].vid[1]].v;
		const Vec3f & p2 = eerie->vertexlist[eerie->facelist[i].vid[2]].v;
		eerie->facelist[i].temp = glm::distance((p0 + p1) * .5f, p2) * glm::distance(p0, p1) * .5f;
	}

	for(size_t i = 0; i < eerie->facelist.size(); i++) {
		CalcObjFaceNormal(
		    &eerie->vertexlist[eerie->facelist[i].vid[0]].v,
		    &eerie->vertexlist[eerie->facelist[i].vid[1]].v,
		    &eerie->vertexlist[eerie->facelist[i].vid[2]].v,
		    &eerie->facelist[i]
		);
		float area = eerie->facelist[i].temp;

		for(long j = 0; j < 3; j++) {
			float mod = area * area;
			Vec3f nrml = eerie->facelist[i].norm * mod;
			float count = mod;

			for(size_t i2 = 0; i2 < eerie->facelist.size(); i2++) {
				if(i != i2) {
					float area2 = eerie->facelist[i].temp;

					for(long j2 = 0; j2 < 3; j2++) {
						if(closerThan(eerie->vertexlist[eerie->facelist[i2].vid[j2]].v, eerie->vertexlist[eerie->facelist[i].vid[j]].v, .1f)) {
							mod = (area2 * area2);
							nrml += eerie->facelist[i2].norm * mod;
							count += mod; 
						}
					}
				}
			}

			count = 1.f / count;
			eerie->vertexlist[eerie->facelist[i].vid[j]].vert.p = nrml * count;
		}
	}

	for(size_t i = 0; i < eerie->facelist.size(); i++) {
		for(long j = 0; j < 3; j++) {
			eerie->vertexlist[eerie->facelist[i].vid[j]].norm = eerie->vertexlist[eerie->facelist[i].vid[j]].vert.p;
		}
	}

	// Apply Normals Spherical correction for NPC head
	long neck_orgn = GetGroupOriginByName(eerie, "neck");
	long head_idx = EERIE_OBJECT_GetGroup(eerie, "head");

	if(head_idx >= 0 && neck_orgn >= 0) {
		VertexGroup & headGroup = eerie->grouplist[head_idx];
		
		Vec3f center = Vec3f_ZERO;
		Vec3f origin = eerie->vertexlist[neck_orgn].v;
		float count = (float)headGroup.indexes.size();

		if(count > 0.f) {
			for(size_t idx = 0 ; idx < headGroup.indexes.size(); idx++) {
				center += eerie->vertexlist[ headGroup.indexes[idx] ].v;
			}
			
			center = (center * (1.f / count) + origin + origin) * (1.0f / 3);
			float max_threshold = glm::distance(origin, center);
			
			for(size_t i = 0; i < headGroup.indexes.size(); i++) {
				EERIE_VERTEX * ev = &eerie->vertexlist[headGroup.indexes[i]];
				float d = glm::distance(ev->v, origin);
				float factor = 1.f;

				if(d < max_threshold) {
					factor = d / max_threshold;
				}

				float ifactor = 1.f - factor;
				Vec3f fakenorm;
				fakenorm = ev->v - center;
				fakenorm = glm::normalize(fakenorm);
				ev->norm = ev->norm * ifactor + fakenorm * factor;
				ev->norm = glm::normalize(ev->norm);
			}
		}
	}

	// NORMALS CALCULATIONS END
	//***********************************************************
	
	eerie->m_skeleton = NULL;
	EERIE_CreateCedricData(eerie);
	return eerie;
}
Пример #27
0
/*!
 * \brief Checks for angular difference between normals
 * \param norm
 * \param norm2
 * \return
 */
static bool LittleAngularDiff(Vec3f * norm, Vec3f * norm2) {
	return closerThan(*norm, *norm2, 1.41421f);
}
Пример #28
0
static bool DirectAddAnchor_Original_Method(EERIE_BACKGROUND * eb, EERIE_BKG_INFO * eg, Vec3f * pos) {
	
	long found = 0;
	long stop_radius = 0;

	Cylinder testcyl;
	Cylinder currcyl;
	Cylinder bestcyl;

	bestcyl.height = 0;
	bestcyl.radius = 0;
	currcyl.radius = 40;
	currcyl.height = -165.f;
	currcyl.origin = *pos;

	stop_radius = 0;
	found = 0;
	long climb = 0;

	while (stop_radius != 1)
	{
		testcyl = currcyl;
		testcyl.radius += INC_RADIUS;

		if (ANCHOR_AttemptValidCylinderPos(testcyl, NULL, CFLAG_NO_INTERCOL | CFLAG_EXTRA_PRECISION | CFLAG_ANCHOR_GENERATION))
		{
			currcyl = testcyl;
			found = 1;
		}
		else
		{
			if ((testcyl.origin.y != currcyl.origin.y)
			        && (glm::abs(testcyl.origin.y - pos->y) < 50))
			{
				testcyl.radius -= INC_RADIUS;
				currcyl = testcyl;
				climb++;
			}
			else
				stop_radius = 1;
		}

		if (climb > 4) stop_radius = 1;

		if (currcyl.radius >= 50.f) stop_radius = 1;

	}

	if(found && currcyl.radius >= bestcyl.radius) {
		bestcyl = currcyl;
	} else {
		return false;
	}

	if(CylinderAboveInvalidZone(bestcyl))
		return false;

	for (long k = 0; k < eb->nbanchors; k++)
	{
		ANCHOR_DATA * ad = &eb->anchors[k];

		if(closerThan(ad->pos, bestcyl.origin, 50.f)) {
			return false;
		}

		if(closerThan(Vec2f(ad->pos.x, ad->pos.z), Vec2f(bestcyl.origin.x, bestcyl.origin.z), 45.f)) {
			
			if (glm::abs(ad->pos.y - bestcyl.origin.y) < 90.f) return false;

			EERIEPOLY * ep = ANCHOR_CheckInPolyPrecis(ad->pos);
			EERIEPOLY * ep2 = ANCHOR_CheckInPolyPrecis(Vec3f(ad->pos.x, bestcyl.origin.y, ad->pos.z));

			if (ep2 == ep) return false;
		}

	}

	eg->ianchors = (long *)realloc(eg->ianchors, sizeof(long) * (eg->nbianchors + 1));

	eg->ianchors[eg->nbianchors] = eb->nbanchors;
	eg->nbianchors++;

	eb->anchors = (ANCHOR_DATA *)realloc(eb->anchors, sizeof(ANCHOR_DATA) * (eb->nbanchors + 1));

	ANCHOR_DATA * ad = &eb->anchors[eb->nbanchors];
	ad->pos = bestcyl.origin;
	ad->height = bestcyl.height;
	ad->radius = bestcyl.radius;
	ad->linked = NULL;
	ad->nblinked = 0;
	ad->flags = 0;
	eb->nbanchors++;
	return true;
}
Пример #29
0
//-----------------------------------------------------------------------------
// Updates all currently launched projectiles
void ARX_MISSILES_Update()
{
	TextureContainer * tc = TC_fire; 

	unsigned long tim = (unsigned long)(arxtime);

	for(unsigned long i(0); i < MAX_MISSILES; i++) {
		if(missiles[i].type == MISSILE_NONE)
			continue;

		long framediff = missiles[i].timecreation + missiles[i].tolive - tim;

		if(framediff < 0) {
			ARX_MISSILES_Kill(i);
			continue;
		}

		long framediff3 = tim - missiles[i].timecreation;

		switch(missiles[i].type) {
			case MISSILE_NONE:
			break;
			case MISSILE_FIREBALL: {
				Vec3f pos;

				pos = missiles[i].startpos + missiles[i].velocity * Vec3f(framediff3);

				if(missiles[i].longinfo != -1) {
					DynLight[missiles[i].longinfo].pos = pos;
				}

				Vec3f orgn = missiles[i].lastpos;
				Vec3f dest = pos;
				
				Vec3f tro = Vec3f(70.f);
				
				EERIEPOLY *ep = GetMinPoly(dest.x, dest.y, dest.z);
				EERIEPOLY *epp = GetMaxPoly(dest.x, dest.y, dest.z);

				if(closerThan(player.pos, pos, 200.f)) {
					ARX_MISSILES_Kill(i);
					ARX_BOOMS_Add(&pos);
					Add3DBoom(&pos);
					DoSphericDamage(&dest, 180.0F, 200.0F, DAMAGE_AREAHALF, DAMAGE_TYPE_FIRE | DAMAGE_TYPE_MAGICAL);
					break;
				}

				if(ep && ep->center.y < dest.y) {
					ARX_MISSILES_Kill(i);
					ARX_BOOMS_Add(&dest);
					Add3DBoom(&dest);
					DoSphericDamage(&dest, 180.0F, 200.0F, DAMAGE_AREAHALF, DAMAGE_TYPE_FIRE | DAMAGE_TYPE_MAGICAL);
					break;
				}

				if(epp && epp->center.y > dest.y) {
					ARX_MISSILES_Kill(i);
					ARX_BOOMS_Add(&dest);
					Add3DBoom(&dest);
					DoSphericDamage(&dest, 180.0F, 200.0F, DAMAGE_AREAHALF, DAMAGE_TYPE_FIRE | DAMAGE_TYPE_MAGICAL);
					break;
				}

				Vec3f hit;
				EERIEPOLY *tp = NULL;
				if(EERIELaunchRay3(&orgn, &dest, &hit, tp, 1)) {
					ARX_MISSILES_Kill(i);
					ARX_BOOMS_Add(&hit);
					Add3DBoom(&hit);
					DoSphericDamage(&dest, 180.0F, 200.0F, DAMAGE_AREAHALF, DAMAGE_TYPE_FIRE | DAMAGE_TYPE_MAGICAL);
					break;
				}

				if(!EECheckInPoly(&dest) || EEIsUnderWater(&dest)) {
					ARX_MISSILES_Kill(i);
					ARX_BOOMS_Add(&dest);
					Add3DBoom(&dest);
					DoSphericDamage(&dest, 180.0F, 200.0F, DAMAGE_AREAHALF, DAMAGE_TYPE_FIRE | DAMAGE_TYPE_MAGICAL);
					break;
				}

				long ici = IsCollidingAnyInter(dest.x, dest.y, dest.z, &tro);

				if(ici != -1 && ici != missiles[i].owner) {
					ARX_MISSILES_Kill(i);
					ARX_BOOMS_Add(&dest);
					Add3DBoom(&dest);
					DoSphericDamage(&dest, 180.0F, 200.0F, DAMAGE_AREAHALF, DAMAGE_TYPE_FIRE | DAMAGE_TYPE_MAGICAL);
					break;
				}
				
				PARTICLE_DEF * pd = createParticle();
				if(pd) {
					pd->ov = pos;
					pd->move = missiles[i].velocity;
					pd->move += Vec3f(3.f - 6.f * rnd(), 4.f - 12.f * rnd(), 3.f - 6.f * rnd());
					pd->tolive = Random::get(500, 1000);
					pd->tc = tc;
					pd->siz = 12.f * float(missiles[i].tolive - framediff3) * (1.f / 4000);
					pd->scale = randomVec(15.f, 20.f);
					pd->special = FIRE_TO_SMOKE;
				}
				
				missiles[i].lastpos = pos;
				
				break;
			}
		}

		missiles[i].lastupdate = tim;
	}
}
Пример #30
0
bool PathFinder::flee(NodeId from, const Vec3f & danger, float safeDist, Result & rlist,
                      bool stealth) const {
	
	static const float FLEE_DISTANCE_COST = 130.0F;
	
	if(!closerThan(map_d[from].pos, danger, safeDist)) {
		rlist.push_back(from);
		return true;
	}
	
	// Create start node and put it on open list
	Node * node = new Node(from, NULL, 0.0f, 0.0f);
	if(!node) {
		return false;
	}
	
	// A* main loop
	OpenNodeList open;
	ClosedNodeList close;
	do {
		
		// Put node onto close list as we have now examined this node.
		close.add(node);
		
		// If it's the goal node then we're done.
		if(node->getCost() == node->getDistance()) {
			buildPath(*node, rlist);
			return true;
		}
		
		NodeId nid = node->getId();
		
		// Otherwise, generate child from current node.
		for(short i(0); i < map_d[nid].nblinked; i++) {
			
			long cid = map_d[nid].linked[i];
			
			if((map_d[cid].flags & ANCHOR_FLAG_BLOCKED) || map_d[cid].height > height
			   || map_d[cid].radius < radius) {
				continue;
			}
			
			if(close.contains(cid)) {
				continue;
			}
			
			// Cost to reach this node.
			float distance = node->getDistance() + fdist(map_d[cid].pos, map_d[nid].pos);
			if(stealth) {
				distance += getIlluminationCost(map_d[cid].pos);
			}
			
			// Estimated cost to get from this node to the destination.
			float remaining = std::max(0.0f, safeDist - fdist(map_d[cid].pos, danger));
			remaining *= FLEE_DISTANCE_COST;
			
			open.add(cid, node, distance, remaining);
		}
		
	} while((node = open.extractBestNode()));
	
	// No path found!
	return false;
}