void FlyingEyeSpell::Update() { const ArxInstant now = arxtime.now(); const ArxDuration framediff3 = now - m_lastupdate; eyeball.floating = std::sin(m_lastupdate - m_timcreation * 0.001f); eyeball.floating *= 10.f; if(m_lastupdate - m_timcreation <= ArxDurationMs(3000)) { eyeball.exist = m_lastupdate - m_timcreation * (1.0f / 30); eyeball.size = Vec3f(1.f - float(eyeball.exist) * 0.01f); eyeball.angle.setYaw(eyeball.angle.getYaw() + toMs(framediff3) * 0.6f); } else { eyeball.exist = 2; } m_lastupdate = now; Entity * io = entities.player(); if(io->obj->fastaccess.primary_attach != ActionPoint()) { Vec3f pos = actionPointPosition(io->obj, io->obj->fastaccess.primary_attach); FlyingEyeSpellUpdateHand(pos, m_light1); } if(io->obj->fastaccess.left_attach != ActionPoint()) { Vec3f pos = actionPointPosition(io->obj, io->obj->fastaccess.left_attach); FlyingEyeSpellUpdateHand(pos, m_light2); } }
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); } } } } }
static void Cedric_AnimateDrawEntityRender(EERIE_3DOBJ * eobj, const Vec3f & pos, Entity * io, float invisibility) { Skeleton *obj = eobj->m_skeleton; if(!obj) return; ColorMod colorMod; colorMod.updateFromEntity(io); /* Get nearest lights */ Vec3f tv = pos; if(io && io->obj->fastaccess.head_group_origin != ObjVertHandle()) { tv.y = io->obj->vertexlist3[io->obj->fastaccess.head_group_origin.handleData()].v.y + 10; } else { tv.y -= 90.f; } ShaderLight lights[llightsSize]; int lightsCount; UpdateLlights(lights, lightsCount, tv, false); Cedric_ApplyLighting(lights, lightsCount, eobj, obj, colorMod); Cedric_RenderObject(eobj, obj, io, pos, invisibility); // Now we can render Linked Objects for(size_t k = 0; k < eobj->linked.size(); k++) { const EERIE_LINKED & link = eobj->linked[k]; if(link.lgroup == ObjVertGroup() || !link.obj) continue; // specific check to avoid drawing player weapon on its back when in subjective view if(io == entities.player() && link.lidx == entities.player()->obj->fastaccess.weapon_attach && !EXTERNALVIEW ) { continue; } TransformInfo t( actionPointPosition(eobj, link.lidx), eobj->m_skeleton->bones[link.lgroup.handleData()].anim.quat, link.io ? link.io->scale : 1.f, link.obj->vertexlist[link.lidx2.handleData()].v - link.obj->vertexlist[link.obj->origin].v); DrawEERIEInter(link.obj, t, link.io, true, invisibility); } }
void SpellBase::updateCasterHand() { // Create hand position if a hand is defined if(m_caster == EntityHandle_Player) { m_hand_group = entities[m_caster]->obj->fastaccess.primary_attach; } else { m_hand_group = entities[m_caster]->obj->fastaccess.left_attach; } if(m_hand_group != ActionPoint()) { m_hand_pos = actionPointPosition(entities[m_caster]->obj, m_hand_group); } }
//*********************************************************************************************** // flags & 1 = blood spawn only //----------------------------------------------------------------------------------------------- //*********************************************************************************************** bool ARX_EQUIPMENT_Strike_Check(Entity * io_source, Entity * io_weapon, float ratioaim, long flags, EntityHandle targ) { ARX_PROFILE_FUNC(); arx_assert(io_source); arx_assert(io_weapon); bool ret = false; EntityHandle source = io_source->index(); EntityHandle weapon = io_weapon->index(); Sphere sphere; EXCEPTIONS_LIST_Pos = 0; float drain_life = ARX_EQUIPMENT_GetSpecialValue(io_weapon, IO_SPECIAL_ELEM_DRAIN_LIFE); float paralyse = ARX_EQUIPMENT_GetSpecialValue(io_weapon, IO_SPECIAL_ELEM_PARALYZE); BOOST_FOREACH(const EERIE_ACTIONLIST & action, io_weapon->obj->actionlist) { float rad = GetHitValue(action.name); if(rad == -1) continue; sphere.origin = actionPointPosition(io_weapon->obj, action.idx); sphere.radius = rad; if(source != PlayerEntityHandle) sphere.radius += 15.f; std::vector<EntityHandle> sphereContent; if(CheckEverythingInSphere(sphere, source, targ, sphereContent)) { BOOST_FOREACH(const EntityHandle & content, sphereContent) { if(ValidIONum(content) && !(entities[content]->ioflags & IO_BODY_CHUNK)) { long HIT_SPARK = 0; EXCEPTIONS_LIST[EXCEPTIONS_LIST_Pos] = content; EXCEPTIONS_LIST_Pos++; if(EXCEPTIONS_LIST_Pos >= MAX_IN_SPHERE) EXCEPTIONS_LIST_Pos--; Entity * target = entities[content]; Vec3f pos; Color color = Color::white; long hitpoint = -1; float curdist = 999999.f; Vec3f vector = (sphere.origin - target->pos) * Vec3f(1.f, 0.5f, 1.f); vector = glm::normalize(vector); for(size_t ii = 0; ii < target->obj->facelist.size(); ii++) { if(target->obj->facelist[ii].facetype & POLY_HIDE) continue; float d = glm::distance(sphere.origin, target->obj->vertexlist3[target->obj->facelist[ii].vid[0]].v); if(d < curdist) { hitpoint = target->obj->facelist[ii].vid[0]; curdist = d; } } if(hitpoint >= 0) { color = (target->ioflags & IO_NPC) ? target->_npcdata->blood_color : Color::white; pos = target->obj->vertexlist3[hitpoint].v; } else ARX_DEAD_CODE(); float dmgs = 0.f; if(!(flags & 1)) { Vec3f posi; if(hitpoint >= 0) { posi = target->obj->vertexlist3[hitpoint].v; dmgs = ARX_EQUIPMENT_ComputeDamages(io_source, target, ratioaim, &posi); } else { dmgs = ARX_EQUIPMENT_ComputeDamages(io_source, target, ratioaim); } if(target->ioflags & IO_NPC) { ret = true; target->spark_n_blood = 0; target->_npcdata->SPLAT_TOT_NB = 0; if(drain_life > 0.f) { float life_gain = std::min(dmgs, drain_life); life_gain = std::min(life_gain, target->_npcdata->lifePool.current); life_gain = std::max(life_gain, 0.f); ARX_DAMAGES_HealInter(io_source, life_gain); } if(paralyse > 0.f) { float ptime = std::min(dmgs * 1000.f, paralyse); ARX_SPELLS_Launch(SPELL_PARALYSE, weapon, SPELLCAST_FLAG_NOMANA | SPELLCAST_FLAG_NOCHECKCANCAST , 5, content, (long)(ptime)); } } if(io_source == entities.player()) ARX_DAMAGES_DurabilityCheck(io_weapon, 0.2f); } if(dmgs > 0.f || ((target->ioflags & IO_NPC) && target->spark_n_blood == SP_BLOODY)) { if(target->ioflags & IO_NPC) { target->spark_n_blood = SP_BLOODY; if(!(flags & 1)) { ARX_PARTICLES_Spawn_Splat(pos, dmgs, color); Sphere sp; float power; power = (dmgs * ( 1.0f / 40 )) + 0.7f; Vec3f vect; vect.x = target->obj->vertexlist3[hitpoint].v.x - io_source->pos.x; vect.y = 0; vect.z = target->obj->vertexlist3[hitpoint].v.z - io_source->pos.z; vect = glm::normalize(vect); sp.origin.x = target->obj->vertexlist3[hitpoint].v.x + vect.x * 30.f; sp.origin.y = target->obj->vertexlist3[hitpoint].v.y; sp.origin.z = target->obj->vertexlist3[hitpoint].v.z + vect.z * 30.f; sp.radius = 3.5f * power * 20; if(CheckAnythingInSphere(sp, PlayerEntityHandle, CAS_NO_NPC_COL)) { Color3f rgb = color.to<float>(); Sphere splatSphere; splatSphere.origin = sp.origin; splatSphere.radius = 30.f; SpawnGroundSplat(splatSphere, rgb, 1); } } ARX_PARTICLES_Spawn_Blood2(pos, dmgs, color, target); } else { if(target->ioflags & IO_ITEM) ARX_PARTICLES_Spawn_Spark(pos, Random::get(0, 3), SpawnSparkType_Default); else ARX_PARTICLES_Spawn_Spark(pos, Random::get(0, 30), SpawnSparkType_Default); ARX_NPC_SpawnAudibleSound(pos, io_source); if(io_source == entities.player()) HIT_SPARK = 1; } } else if((target->ioflags & IO_NPC) && (dmgs <= 0.f || target->spark_n_blood == SP_SPARKING)) { unsigned int nb; if(target->spark_n_blood == SP_SPARKING) nb = Random::get(0, 3); else nb = 30; if(target->ioflags & IO_ITEM) nb = 1; ARX_PARTICLES_Spawn_Spark(pos, nb, SpawnSparkType_Default); ARX_NPC_SpawnAudibleSound(pos, io_source); target->spark_n_blood = SP_SPARKING; if(!(target->ioflags & IO_NPC)) HIT_SPARK = 1; } else if(dmgs <= 0.f && ((target->ioflags & IO_FIX) || (target->ioflags & IO_ITEM))) { unsigned int nb; if(target->spark_n_blood == SP_SPARKING) nb = Random::get(0, 3); else nb = 30; if(target->ioflags & IO_ITEM) nb = 1; ARX_PARTICLES_Spawn_Spark(pos, nb, SpawnSparkType_Default); ARX_NPC_SpawnAudibleSound(pos, io_source); target->spark_n_blood = SP_SPARKING; if (!(target->ioflags & IO_NPC)) HIT_SPARK = 1; } if(HIT_SPARK) { if(!io_source->isHit) { ARX_DAMAGES_DurabilityCheck(io_weapon, 1.f); io_source->isHit = true; std::string _weapon_material = "metal"; const std::string * weapon_material = &_weapon_material; if(!io_weapon->weaponmaterial.empty()) { weapon_material = &io_weapon->weaponmaterial; } char bkg_material[128]; if(ARX_MATERIAL_GetNameById(target->material, bkg_material)) ARX_SOUND_PlayCollision(*weapon_material, bkg_material, 1.f, 1.f, sphere.origin, NULL); } } } } } const EERIEPOLY * ep = CheckBackgroundInSphere(sphere); if(ep) { if(io_source == entities.player()) { if(!io_source->isHit) { ARX_DAMAGES_DurabilityCheck(io_weapon, 1.f); io_source->isHit = true; std::string _weapon_material = "metal"; const std::string * weapon_material = &_weapon_material; if(!io_weapon->weaponmaterial.empty()) { weapon_material = &io_weapon->weaponmaterial; } std::string bkg_material = "earth"; if(ep && ep->tex && !ep->tex->m_texName.empty()) bkg_material = GetMaterialString(ep->tex->m_texName); ARX_SOUND_PlayCollision(*weapon_material, bkg_material, 1.f, 1.f, sphere.origin, io_source); } } ARX_PARTICLES_Spawn_Spark(sphere.origin, Random::get(0, 10), SpawnSparkType_Default); ARX_NPC_SpawnAudibleSound(sphere.origin, io_source); } } return ret; }
void FlyingEyeSpell::Update(float timeDelta) { ARX_UNUSED(timeDelta); const unsigned long tim = (unsigned long)(arxtime); const long framediff3 = tim - m_lastupdate; eyeball.floating = std::sin(m_lastupdate-m_timcreation * 0.001f); eyeball.floating *= 10.f; if(m_lastupdate-m_timcreation <= 3000) { eyeball.exist = m_lastupdate - m_timcreation * (1.0f / 30); eyeball.size = Vec3f(1.f - float(eyeball.exist) * 0.01f); eyeball.angle.setPitch(eyeball.angle.getPitch() + framediff3 * 0.6f); } else { eyeball.exist = 2; } m_lastupdate=tim; Entity * io = entities.player(); EERIE_3DOBJ * eobj = io->obj; long pouet = 2; while(pouet) { ActionPoint id; if(pouet == 2) id = io->obj->fastaccess.primary_attach; else id = GetActionPointIdx(io->obj, "left_attach"); pouet--; if(id != ActionPoint()) { if(!lightHandleIsValid(special[pouet])) { special[pouet] = GetFreeDynLight(); } if(lightHandleIsValid(special[pouet])) { EERIE_LIGHT * el = lightHandleGet(special[pouet]); el->intensity = 1.3f; el->fallend = 180.f; el->fallstart = 50.f; el->rgb = Color3f(0.7f, 0.3f, 1.f); el->pos = actionPointPosition(eobj, id); } for(long kk = 0; kk < 2; kk++) { PARTICLE_DEF * pd = createParticle(); if(!pd) { break; } pd->ov = actionPointPosition(eobj, id) + randomVec(-1.f, 1.f); pd->move = Vec3f(0.1f, 0.f, 0.1f) + Vec3f(-0.2f, -2.2f, -0.2f) * randomVec3f(); pd->siz = 5.f; pd->tolive = Random::get(1500, 3500); pd->scale = Vec3f(0.2f); pd->tc = TC_smoke; pd->special = FADE_IN_AND_OUT | ROTATING | MODULATE_ROTATION | DISSIPATING; pd->sourceionum = PlayerEntityHandle; pd->source = &eobj->vertexlist3[id.handleData()].v; // FIXME passing of pointer to vertex position pd->fparam = 0.0000001f; pd->rgb = Color3f(.7f, .3f, 1.f) + Color3f(-.1f, -.1f, -.1f) * randomColor3f(); } } } }
void MagicMissileSpell::Launch() { m_duration = ArxDurationMs(6000); m_hand_group = GetActionPointIdx(entities[m_caster]->obj, "primary_attach"); if(m_hand_group != ActionPoint()) { Entity * caster = entities[m_caster]; ActionPoint group = m_hand_group; m_hand_pos = actionPointPosition(caster->obj, group); } Vec3f startPos; float pitch, yaw; if(m_caster == EntityHandle_Player) { yaw = player.angle.getYaw(); pitch = player.angle.getPitch(); Vec3f vector = angleToVector(Anglef(pitch, yaw, 0.f)) * 60.f; if(m_hand_group != ActionPoint()) { startPos = m_hand_pos; } else { startPos = player.pos; startPos += angleToVectorXZ(yaw); } startPos += vector; } else { pitch = 0; yaw = entities[m_caster]->angle.getYaw(); Vec3f vector = angleToVector(Anglef(pitch, yaw, 0.f)) * 60.f; if(m_hand_group != ActionPoint()) { startPos = m_hand_pos; } else { startPos = entities[m_caster]->pos; } startPos += vector; Entity * io = entities[m_caster]; if(ValidIONum(io->targetinfo)) { const Vec3f & p1 = m_caster_pos; const Vec3f & p2 = entities[io->targetinfo]->pos; pitch = -(glm::degrees(getAngle(p1.y, p1.z, p2.y, p2.z + glm::distance(Vec2f(p2.x, p2.z), Vec2f(p1.x, p1.z))))); //alpha entre orgn et dest; } else if (ValidIONum(m_target)) { const Vec3f & p1 = m_caster_pos; const Vec3f & p2 = entities[m_target]->pos; pitch = -(glm::degrees(getAngle(p1.y, p1.z, p2.y, p2.z + glm::distance(Vec2f(p2.x, p2.z), Vec2f(p1.x, p1.z))))); //alpha entre orgn et dest; } } m_mrCheat = (m_caster == EntityHandle_Player && cur_mr == 3); ArxDuration lMax = ArxDuration_ZERO; long number; if(sp_max || cur_rf == 3) { number = long(m_level); } else { number = glm::clamp(long(m_level + 1) / 2, 1l, 5l); } pTab.reserve(number); for(size_t i = 0; i < size_t(number); i++) { CMagicMissile * missile = NULL; if(!m_mrCheat) { missile = new CMagicMissile(); } else { missile = new MrMagicMissileFx(); } pTab.push_back(missile); Anglef angles(pitch, yaw, 0.f); if(i > 0) { angles.setPitch(angles.getPitch() + Random::getf(-4.0f, 4.0f)); angles.setYaw(angles.getYaw() + Random::getf(-6.0f, 6.0f)); } missile->Create(startPos, angles); ArxDuration lTime = m_duration + ArxDurationMs(Random::get(-1000, 1000)); lTime = std::max(ArxDurationMs(1000), lTime); lMax = std::max(lMax, lTime); missile->SetDuration(lTime); EERIE_LIGHT * el = dynLightCreate(missile->lLightId); if(el) { el->intensity = 0.7f + 2.3f; el->fallend = 190.f; el->fallstart = 80.f; if(m_mrCheat) { el->rgb = Color3f(1.f, 0.3f, 0.8f); } else { el->rgb = Color3f(0.f, 0.f, 1.f); } el->pos = startPos; el->duration = ArxDurationMs(300); } } m_duration = lMax + ArxDurationMs(1000); }
void ManageCombatModeAnimations() { arx_assert(entities.player()); if(player.m_aimTime > 0) { player.m_aimTime += g_platformTime.lastFrameDuration(); } Entity * const io = entities.player(); AnimLayer & layer1 = io->animlayer[1]; ANIM_HANDLE ** alist = io->anims; WeaponType weapontype = ARX_EQUIPMENT_GetPlayerWeaponType(); if(weapontype == WEAPON_BARE && LAST_WEAPON_TYPE != weapontype) { if(layer1.cur_anim != alist[ANIM_BARE_WAIT]) { changeAnimation(io, 1, alist[ANIM_BARE_WAIT]); player.m_aimTime = 0; } } switch(weapontype) { case WEAPON_BARE: { // BARE HANDS PLAYER MANAGEMENT if(layer1.cur_anim == alist[ANIM_BARE_WAIT]) { player.m_aimTime = 0; if(eeMousePressed1()) { changeAnimation(io, 1, alist[ANIM_BARE_STRIKE_LEFT_START + player.m_strikeDirection * 3]); io->isHit = false; } } // Now go for strike cycle... for(long j = 0; j < 4; j++) { if(layer1.cur_anim == alist[ANIM_BARE_STRIKE_LEFT_START + j * 3] && (layer1.flags & EA_ANIMEND)) { changeAnimation(io, 1, alist[ANIM_BARE_STRIKE_LEFT_CYCLE + j * 3], EA_LOOP); player.m_aimTime = PlatformDuration::ofRaw(1); } else if(layer1.cur_anim == alist[ANIM_BARE_STRIKE_LEFT_CYCLE + j * 3] && !eeMousePressed1()) { changeAnimation(io, 1, alist[ANIM_BARE_STRIKE_LEFT + j * 3]); strikeSpeak(io); SendIOScriptEvent(NULL, io, SM_STRIKE, "bare"); player.m_weaponBlocked = AnimationDuration::ofRaw(-1); // TODO inband signaling AnimationDuration player.m_strikeDirection = 0; player.m_aimTime = 0; } else if(layer1.cur_anim == alist[ANIM_BARE_STRIKE_LEFT + j * 3]) { if(layer1.flags & EA_ANIMEND) { changeAnimation(io, 1, alist[ANIM_BARE_WAIT], EA_LOOP); player.m_strikeDirection = 0; player.m_aimTime = PlatformDuration::ofRaw(1); player.m_weaponBlocked = AnimationDuration::ofRaw(-1); } else if( layer1.ctime > layer1.currentAltAnim()->anim_time * 0.2f && layer1.ctime < layer1.currentAltAnim()->anim_time * 0.8f && player.m_weaponBlocked == AnimationDuration::ofRaw(-1)) { ActionPoint id = ActionPoint(); if(layer1.cur_anim == alist[ANIM_BARE_STRIKE_LEFT]) { id = io->obj->fastaccess.left_attach; } else { // Strike Right id = io->obj->fastaccess.primary_attach; } if(id != ActionPoint()) { Sphere sphere; sphere.origin = actionPointPosition(io->obj, id); sphere.radius = 25.f; EntityHandle num; if(CheckAnythingInSphere(sphere, EntityHandle_Player, 0, &num)) { float dmgs = (player.m_miscFull.damages + 1) * player.m_strikeAimRatio; if(ARX_DAMAGES_TryToDoDamage(actionPointPosition(io->obj, id), dmgs, 40, EntityHandle_Player)) { player.m_weaponBlocked = layer1.ctime; } ParticleSparkSpawnContinous(sphere.origin, unsigned(dmgs), SpawnSparkType_Success); if(ValidIONum(num)) { static PlatformInstant lastHit = 0; PlatformInstant now = g_platformTime.frameStart(); if(now - lastHit > toPlatformDuration(layer1.ctime)) { ARX_SOUND_PlayCollision(entities[num]->material, MATERIAL_FLESH, 1.f, 1.f, sphere.origin, NULL); lastHit = now; } } } } } } } break; } case WEAPON_DAGGER: { // DAGGER PLAYER MANAGEMENT // Waiting and receiving Strike Impulse if(layer1.cur_anim == alist[ANIM_DAGGER_WAIT]) { player.m_aimTime = 0; if(eeMousePressed1()) { changeAnimation(io, 1, alist[ANIM_DAGGER_STRIKE_LEFT_START + player.m_strikeDirection * 3]); io->isHit = false; } } // Now go for strike cycle... for(long j = 0; j < 4; j++) { if(layer1.cur_anim == alist[ANIM_DAGGER_STRIKE_LEFT_START + j * 3] && (layer1.flags & EA_ANIMEND)) { changeAnimation(io, 1, alist[ANIM_DAGGER_STRIKE_LEFT_CYCLE + j * 3], EA_LOOP); player.m_aimTime = PlatformDuration::ofRaw(1); } else if(layer1.cur_anim == alist[ANIM_DAGGER_STRIKE_LEFT_CYCLE + j * 3] && !eeMousePressed1()) { changeAnimation(io, 1, alist[ANIM_DAGGER_STRIKE_LEFT + j * 3]); strikeSpeak(io); SendIOScriptEvent(NULL, io, SM_STRIKE, "dagger"); player.m_strikeDirection = 0; player.m_aimTime = 0; } else if(layer1.cur_anim == alist[ANIM_DAGGER_STRIKE_LEFT + j * 3]) { if( layer1.ctime > layer1.currentAltAnim()->anim_time * 0.3f && layer1.ctime < layer1.currentAltAnim()->anim_time * 0.7f ) { Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]]; if(player.m_weaponBlocked == AnimationDuration::ofRaw(-1) && ARX_EQUIPMENT_Strike_Check(io, weapon, player.m_strikeAimRatio, 0)) { player.m_weaponBlocked = layer1.ctime; } } if(layer1.flags & EA_ANIMEND) { changeAnimation(io, 1, alist[ANIM_DAGGER_WAIT], EA_LOOP); layer1.flags &= ~(EA_PAUSED | EA_REVERSE); player.m_strikeDirection = 0; player.m_aimTime = PlatformDuration::ofRaw(1); player.m_weaponBlocked = AnimationDuration::ofRaw(-1); } if( player.m_weaponBlocked != AnimationDuration::ofRaw(-1) && layer1.ctime < layer1.currentAltAnim()->anim_time * 0.9f ) { Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]]; ARX_EQUIPMENT_Strike_Check(io, weapon, player.m_strikeAimRatio, 1); } } } break; } case WEAPON_1H: { // 1HANDED PLAYER MANAGEMENT // Waiting and Received Strike Impulse if(layer1.cur_anim == alist[ANIM_1H_WAIT]) { player.m_aimTime = 0; if(eeMousePressed1()) { changeAnimation(io, 1, alist[ANIM_1H_STRIKE_LEFT_START + player.m_strikeDirection * 3]); io->isHit = false; } } // Now go for strike cycle... for(long j = 0; j < 4; j++) { if(layer1.cur_anim == alist[ANIM_1H_STRIKE_LEFT_START + j * 3] && (layer1.flags & EA_ANIMEND)) { changeAnimation(io, 1, alist[ANIM_1H_STRIKE_LEFT_CYCLE + j * 3], EA_LOOP); player.m_aimTime = PlatformDuration::ofRaw(1); } else if(layer1.cur_anim == alist[ANIM_1H_STRIKE_LEFT_CYCLE + j * 3] && !eeMousePressed1()) { changeAnimation(io, 1, alist[ANIM_1H_STRIKE_LEFT + j * 3]); strikeSpeak(io); SendIOScriptEvent(NULL, io, SM_STRIKE, "1h"); player.m_strikeDirection = 0; player.m_aimTime = 0; } else if(layer1.cur_anim == alist[ANIM_1H_STRIKE_LEFT + j * 3]) { if( layer1.ctime > layer1.currentAltAnim()->anim_time * 0.3f && layer1.ctime < layer1.currentAltAnim()->anim_time * 0.7f ) { Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]]; if(player.m_weaponBlocked == AnimationDuration::ofRaw(-1) && ARX_EQUIPMENT_Strike_Check(io, weapon, player.m_strikeAimRatio, 0)) { player.m_weaponBlocked = layer1.ctime; } } if(layer1.flags & EA_ANIMEND) { changeAnimation(io, 1, alist[ANIM_1H_WAIT], EA_LOOP); layer1.flags &= ~(EA_PAUSED | EA_REVERSE); player.m_strikeDirection = 0; player.m_aimTime = 0; player.m_weaponBlocked = AnimationDuration::ofRaw(-1); } if( player.m_weaponBlocked != AnimationDuration::ofRaw(-1) && layer1.ctime < layer1.currentAltAnim()->anim_time * 0.9f ) { Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]]; ARX_EQUIPMENT_Strike_Check(io, weapon, player.m_strikeAimRatio, 1); } } } break; } case WEAPON_2H: { // 2HANDED PLAYER MANAGEMENT // Waiting and Receiving Strike Impulse if(layer1.cur_anim == alist[ANIM_2H_WAIT]) { player.m_aimTime = 0; if(eeMousePressed1()) { changeAnimation(io, 1, alist[ANIM_2H_STRIKE_LEFT_START + player.m_strikeDirection * 3]); io->isHit = false; } } // Now go for strike cycle... for(long j = 0; j < 4; j++) { if(layer1.cur_anim == alist[ANIM_2H_STRIKE_LEFT_START + j * 3] && (layer1.flags & EA_ANIMEND)) { changeAnimation(io, 1, alist[ANIM_2H_STRIKE_LEFT_CYCLE + j * 3], EA_LOOP); player.m_aimTime = PlatformDuration::ofRaw(1); } else if(layer1.cur_anim == alist[ANIM_2H_STRIKE_LEFT_CYCLE + j * 3] && !eeMousePressed1()) { changeAnimation(io, 1, alist[ANIM_2H_STRIKE_LEFT + j * 3]); strikeSpeak(io); SendIOScriptEvent(NULL, io, SM_STRIKE, "2h"); player.m_strikeDirection = 0; player.m_aimTime = 0; } else if(layer1.cur_anim == alist[ANIM_2H_STRIKE_LEFT + j * 3]) { if( layer1.ctime > layer1.currentAltAnim()->anim_time * 0.3f && layer1.ctime < layer1.currentAltAnim()->anim_time * 0.7f ) { Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]]; if(player.m_weaponBlocked == AnimationDuration::ofRaw(-1) && ARX_EQUIPMENT_Strike_Check(io, weapon, player.m_strikeAimRatio, 0)) { player.m_weaponBlocked = layer1.ctime; } } if(layer1.flags & EA_ANIMEND) { changeAnimation(io, 1, alist[ANIM_2H_WAIT], EA_LOOP); layer1.flags &= ~(EA_PAUSED | EA_REVERSE); player.m_strikeDirection = 0; player.m_aimTime = 0; player.m_weaponBlocked = AnimationDuration::ofRaw(-1); } if( player.m_weaponBlocked != AnimationDuration::ofRaw(-1) && layer1.ctime < layer1.currentAltAnim()->anim_time * 0.9f ) { Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]]; ARX_EQUIPMENT_Strike_Check(io, weapon, player.m_strikeAimRatio, 1); } } } break; } case WEAPON_BOW: { // MISSILE PLAYER MANAGEMENT if(layer1.cur_anim == alist[ANIM_MISSILE_STRIKE_CYCLE]) { player.m_bowAimRatio += bowZoomFromDuration(toMs(g_platformTime.lastFrameDuration())); if(player.m_bowAimRatio > 1.f) player.m_bowAimRatio = 1.f; } // Waiting and Receiving Strike Impulse if(layer1.cur_anim == alist[ANIM_MISSILE_WAIT]) { player.m_aimTime = PlatformDuration::ofRaw(1); if(eeMousePressed1() && Player_Arrow_Count() > 0) { changeAnimation(io, 1, alist[ANIM_MISSILE_STRIKE_PART_1]); io->isHit = false; } } if(layer1.cur_anim == alist[ANIM_MISSILE_STRIKE_PART_1] && (layer1.flags & EA_ANIMEND)) { player.m_aimTime = 0; changeAnimation(io, 1, alist[ANIM_MISSILE_STRIKE_PART_2]); EERIE_LINKEDOBJ_LinkObjectToObject(io->obj, arrowobj, "left_attach", "attach", NULL); } // Now go for strike cycle... if(layer1.cur_anim == alist[ANIM_MISSILE_STRIKE_PART_2] && (layer1.flags & EA_ANIMEND)) { changeAnimation(io, 1, alist[ANIM_MISSILE_STRIKE_CYCLE], EA_LOOP); player.m_aimTime = PlatformDuration::ofRaw(1); } else if(layer1.cur_anim == alist[ANIM_MISSILE_STRIKE_CYCLE] && !eeMousePressed1()) { EERIE_LINKEDOBJ_UnLinkObjectFromObject(io->obj, arrowobj); changeAnimation(io, 1, alist[ANIM_MISSILE_STRIKE]); SendIOScriptEvent(NULL, io, SM_STRIKE, "bow"); StrikeAimtime(); player.m_strikeAimRatio = player.m_bowAimRatio; Entity * quiver = Player_Arrow_Count_Decrease(); float poisonous = 0.f; if(quiver) { poisonous = quiver->poisonous; if(quiver->poisonous_count > 0) { quiver->poisonous_count--; if(quiver->poisonous_count <= 0) quiver->poisonous = 0; } ARX_DAMAGES_DurabilityLoss(quiver, 1.f); // TODO is this needed ?, quivers seem to self destruct via script, but maybe not all if(ValidIOAddress(quiver) && quiver->durability <= 0.f) { ARX_INTERACTIVE_DestroyIOdelayed(quiver); } } float aimratio = player.m_strikeAimRatio; if(sp_max && poisonous < 3.f) poisonous = 3.f; Vec3f orgPos = player.pos + Vec3f(0.f, 40.f, 0.f); if(io->obj->fastaccess.left_attach != ActionPoint()) { orgPos = actionPointPosition(io->obj, io->obj->fastaccess.left_attach); } Anglef orgAngle = player.angle; PlayerLaunchArrow_Test(aimratio, poisonous, orgPos, orgAngle); if(sp_max) { Anglef angle; Vec3f pos = player.pos + Vec3f(0.f, 40.f, 0.f); angle.setPitch(player.angle.getPitch()); angle.setYaw(player.angle.getYaw() + 8); angle.setRoll(player.angle.getRoll()); PlayerLaunchArrow_Test(aimratio, poisonous, pos, angle); angle.setPitch(player.angle.getPitch()); angle.setYaw(player.angle.getYaw() - 8); PlayerLaunchArrow_Test(aimratio, poisonous, pos, angle); angle.setPitch(player.angle.getPitch()); angle.setYaw(player.angle.getYaw() + 4.f); PlayerLaunchArrow_Test(aimratio, poisonous, pos, angle); angle.setPitch(player.angle.getPitch()); angle.setYaw(player.angle.getYaw() - 4.f); PlayerLaunchArrow_Test(aimratio, poisonous, pos, angle); } player.m_aimTime = 0; } else if(layer1.cur_anim == alist[ANIM_MISSILE_STRIKE]) { player.m_bowAimRatio -= bowZoomFromDuration(toMs(g_platformTime.lastFrameDuration())); if(player.m_bowAimRatio < 0) player.m_bowAimRatio = 0; if(layer1.flags & EA_ANIMEND) { player.m_bowAimRatio = 0; changeAnimation(io, 1, alist[ANIM_MISSILE_WAIT], EA_LOOP); player.m_aimTime = 0; player.m_weaponBlocked = AnimationDuration::ofRaw(-1); EERIE_LINKEDOBJ_UnLinkObjectFromObject(io->obj, arrowobj); } } break; } } LAST_WEAPON_TYPE = weapontype; }
void PoisonProjectileSpell::Launch() { ARX_SOUND_PlaySFX(g_snd.SPELL_POISON_PROJECTILE_LAUNCH, &m_caster_pos); Vec3f srcPos(0.f); float afBeta = 0.f; Entity * caster = entities[m_caster]; m_hand_group = caster->obj->fastaccess.primary_attach; if(m_hand_group != ActionPoint()) { ActionPoint group = m_hand_group; m_hand_pos = actionPointPosition(caster->obj, group); } if(m_caster == EntityHandle_Player) { afBeta = player.angle.getYaw(); if(m_hand_group != ActionPoint()) { srcPos = m_hand_pos; } else { srcPos = player.pos; } } else { afBeta = entities[m_caster]->angle.getYaw(); if(m_hand_group != ActionPoint()) { srcPos = m_hand_pos; } else { srcPos = entities[m_caster]->pos; } } srcPos += angleToVectorXZ(afBeta) * 90.f; size_t uiNumber = glm::clamp(static_cast<unsigned int>(m_level), 1u, 5u); for(size_t i = 0; i < uiNumber; i++) { CPoisonProjectile * projectile = new CPoisonProjectile(); m_projectiles.push_back(projectile); } m_duration = GameDurationMs(8000); m_hasDuration = true; GameDuration lMax = 0; for(size_t i = 0; i < m_projectiles.size(); i++) { CPoisonProjectile * projectile = m_projectiles[i]; projectile->Create(srcPos, afBeta + Random::getf(-10.f, 10.f)); GameDuration lTime = m_duration + GameDurationMs(Random::getu(0, 5000)); projectile->SetDuration(lTime); lMax = std::max(lMax, lTime); EERIE_LIGHT * light = dynLightCreate(projectile->lLightId); if(light) { light->intensity = 2.3f; light->fallend = 250.f; light->fallstart = 150.f; light->rgb = Color3f::green; light->pos = projectile->eSrc; light->creationTime = g_gameTime.now(); light->duration = GameDurationMs(200); } } m_duration = lMax + GameDurationMs(1000); }
void ARX_THROWN_OBJECT_Manage(float time_offset) { for(size_t i = 0; i < MAX_THROWN_OBJECTS; i++) { Projectile & projectile = g_projectiles[i]; if(!(projectile.flags & ATO_EXIST)) continue; { // Is Object Visible & Near ? EERIE_BKG_INFO * bkgData = getFastBackgroundData(projectile.position.x, projectile.position.z); if(!bkgData || !bkgData->treat) { continue; } // Now render object ! if(!projectile.obj) continue; TransformInfo t(projectile.position, projectile.quat); DrawEERIEInter_ModelTransform(projectile.obj, t); if((projectile.flags & ATO_FIERY) && (projectile.flags & ATO_MOVING) && !(projectile.flags & ATO_UNDERWATER)) { LightHandle id = GetFreeDynLight(); if(lightHandleIsValid(id) && g_framedelay > 0) { EERIE_LIGHT * light = lightHandleGet(id); light->intensity = 1.f; light->fallstart = 100.f; light->fallend = 240.f; light->rgb = Color3f(1.f, .8f, .6f) - randomColor3f() * Color3f(.2f, .2f, .2f); light->pos = projectile.position; light->ex_flaresize = 40.f; light->extras |= EXTRAS_FLARE; light->duration = static_cast<unsigned long>(g_framedelay * 0.5f); } createObjFireParticles(projectile.obj, 6, 2, 180); } if(projectile.m_trail) { projectile.m_trail->SetNextPosition(projectile.position); projectile.m_trail->Update(time_offset); } if(projectile.flags & ATO_MOVING) { long need_kill = 0; float mod = time_offset * projectile.velocity; Vec3f original_pos = projectile.position; projectile.position.x += projectile.vector.x * mod; float gmod = 1.f - projectile.velocity; gmod = glm::clamp(gmod, 0.f, 1.f); projectile.position.y += projectile.vector.y * mod + (time_offset * gmod); projectile.position.z += projectile.vector.z * mod; CheckForIgnition(Sphere(original_pos, 10.f), 0, 2); Vec3f wpos = projectile.position; wpos.y += 20.f; EERIEPOLY * ep = EEIsUnderWater(wpos); if(projectile.flags & ATO_UNDERWATER) { if(!ep) { projectile.flags &= ~ATO_UNDERWATER; ARX_SOUND_PlaySFX(SND_PLOUF, &projectile.position); } } else if(ep) { projectile.flags |= ATO_UNDERWATER; ARX_SOUND_PlaySFX(SND_PLOUF, &projectile.position); } // Check for collision MUST be done after DRAWING !!!! long nbact = projectile.obj->actionlist.size(); for(long j = 0; j < nbact; j++) { float rad = GetHitValue(projectile.obj->actionlist[j].name); if(rad == -1) continue; rad *= .5f; const Vec3f v0 = actionPointPosition(projectile.obj, projectile.obj->actionlist[j].idx); Vec3f dest = original_pos + projectile.vector * 95.f; Vec3f orgn = original_pos - projectile.vector * 25.f; EERIEPOLY * ep = CheckArrowPolyCollision(orgn, dest); if(ep) { ARX_PARTICLES_Spawn_Spark(v0, 14, SpawnSparkType_Default); CheckExp(projectile); if(ValidIONum(projectile.source)) ARX_NPC_SpawnAudibleSound(v0, entities[projectile.source]); projectile.flags &= ~ATO_MOVING; projectile.velocity = 0.f; std::string bkg_material = "earth"; if(ep && ep->tex && !ep->tex->m_texName.empty()) bkg_material = GetMaterialString(ep->tex->m_texName); if(ValidIONum(projectile.source)) { char weapon_material[64] = "dagger"; ARX_SOUND_PlayCollision(weapon_material, bkg_material, 1.f, 1.f, v0, entities[projectile.source]); } projectile.position = original_pos; j = 200; } else if(IsPointInField(v0)) { ARX_PARTICLES_Spawn_Spark(v0, 24, SpawnSparkType_Default); CheckExp(projectile); if (ValidIONum(projectile.source)) ARX_NPC_SpawnAudibleSound(v0, entities[projectile.source]); projectile.flags &= ~ATO_MOVING; projectile.velocity = 0.f; if(ValidIONum(projectile.source)) { char weapon_material[64] = "dagger"; char bkg_material[64] = "earth"; ARX_SOUND_PlayCollision(weapon_material, bkg_material, 1.f, 1.f, v0, entities[projectile.source]); } projectile.position = original_pos; j = 200; need_kill = 1; } else { for(float precision = 0.5f; precision <= 6.f; precision += 0.5f) { Sphere sphere; sphere.origin = v0 + projectile.vector * precision * 4.5f; sphere.radius = rad + 3.f; std::vector<EntityHandle> sphereContent; if(CheckEverythingInSphere(sphere, projectile.source, EntityHandle(), sphereContent)) { for(size_t jj = 0; jj < sphereContent.size(); jj++) { if(ValidIONum(sphereContent[jj]) && sphereContent[jj] != projectile.source) { Entity * target = entities[sphereContent[jj]]; if(target->ioflags & IO_NPC) { Vec3f pos; Color color = Color::none; long hitpoint = -1; float curdist = 999999.f; for(size_t ii = 0 ; ii < target->obj->facelist.size() ; ii++) { if(target->obj->facelist[ii].facetype & POLY_HIDE) continue; short vid = target->obj->facelist[ii].vid[0]; float d = glm::distance(sphere.origin, target->obj->vertexlist3[vid].v); if(d < curdist) { hitpoint = target->obj->facelist[ii].vid[0]; curdist = d; } } if(hitpoint >= 0) { color = target->_npcdata->blood_color; pos = target->obj->vertexlist3[hitpoint].v; } if(projectile.source == PlayerEntityHandle) { float damages = ARX_THROWN_ComputeDamages(projectile, projectile.source, sphereContent[jj]); if(damages > 0.f) { arx_assert(hitpoint >= 0); if(target->ioflags & IO_NPC) { target->_npcdata->SPLAT_TOT_NB = 0; ARX_PARTICLES_Spawn_Blood2(original_pos, damages, color, target); } ARX_PARTICLES_Spawn_Blood2(pos, damages, color, target); ARX_DAMAGES_DamageNPC(target, damages, projectile.source, false, &pos); if(Random::getf(0.f, 100.f) > target->_npcdata->resist_poison) { target->_npcdata->poisonned += projectile.poisonous; } CheckExp(projectile); } else { ARX_PARTICLES_Spawn_Spark(v0, 14, SpawnSparkType_Default); ARX_NPC_SpawnAudibleSound(v0, entities[projectile.source]); } } } else { // not NPC if(target->ioflags & IO_FIX) { if(ValidIONum(projectile.source)) ARX_DAMAGES_DamageFIX(target, 0.1f, projectile.source, false); } ARX_PARTICLES_Spawn_Spark(v0, 14, SpawnSparkType_Default); if(ValidIONum(projectile.source)) ARX_NPC_SpawnAudibleSound(v0, entities[projectile.source]); CheckExp(projectile); } // Need to deal damages ! projectile.flags &= ~ATO_MOVING; projectile.velocity = 0.f; need_kill = 1; precision = 500.f; j = 200; } } } } } } if(need_kill) ARX_THROWN_OBJECT_Kill(i); } } } }