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); } } } }
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; }
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(); } }
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); } } } } }
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; } } } } }
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); } }
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]); } } }
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--; } } } }
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); } } }
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); } } }
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); }
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; } } } }
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; }
//----------------------------------------------------------------------------- // 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; } }
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; } } } } }
//----------------------------------------------------------------------------- // 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; } }
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; } } }
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; }
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); } }
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; } } } }
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; } } }
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); }
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); } } } } }
// 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; }
/*! * \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); }
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; }
//----------------------------------------------------------------------------- // 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; } }
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; }