//*********************************************************************************************** // flags & 1 == destroyed ! //*********************************************************************************************** void ARX_EQUIPMENT_UnEquip(Entity * target, Entity * tounequip, long flags) { if(!target || !tounequip) return; if(target != entities.player()) return; for(size_t i = 0; i < MAX_EQUIPED; i++) { if(ValidIONum(player.equiped[i]) && entities[player.equiped[i]] == tounequip) { EERIE_LINKEDOBJ_UnLinkObjectFromObject(target->obj, tounequip->obj); ARX_EQUIPMENT_Release(player.equiped[i]); target->bbox2D.min.x = 9999; target->bbox2D.max.x = -9999; if(!flags) { if(!DRAGINTER) { ARX_SOUND_PlayInterface(SND_INVSTD); Set_DragInter(tounequip); } else { giveToPlayer(tounequip); } } EVENT_SENDER = tounequip; SendIOScriptEvent(entities.player(), SM_EQUIPOUT); EVENT_SENDER = entities.player(); SendIOScriptEvent(tounequip, SM_EQUIPOUT); } } if(tounequip->type_flags & (OBJECT_TYPE_HELMET | OBJECT_TYPE_ARMOR | OBJECT_TYPE_LEGGINGS)) ARX_EQUIPMENT_RecreatePlayerMesh(); }
static void EntityLeavingLastZone(Entity * io, ARX_PATH * last) { SendIOScriptEvent(NULL, io, SM_LEAVEZONE, last->name); if(!last->controled.empty()) { EntityHandle t = entities.getById(last->controled); if(t != EntityHandle()) { ScriptParameters parameters; parameters.push_back(io->idString()); parameters.push_back(last->name); SendIOScriptEvent(NULL, entities[t], SM_CONTROLLEDZONE_LEAVE, parameters); } } }
void SecondaryInventoryHud::updateFader() { if(m_fadeDirection != Fade_stable) { if((player.Interface & INTER_COMBATMODE) || player.doingmagic >= 2 || m_fadeDirection == Fade_left) { if(m_fadePosition > -160) m_fadePosition -= (g_framedelay * ( 1.0f / 3 )) * m_scale; } else { if(m_fadePosition < 0) m_fadePosition += m_fadeDirection * (g_framedelay * ( 1.0f / 3 )) * m_scale; } if(m_fadePosition <= -160) { m_fadePosition = -160; m_fadeDirection = Fade_stable; if(player.Interface & INTER_STEAL || ioSteal) { SendIOScriptEvent(ioSteal, SM_STEAL, "off"); player.Interface &= ~INTER_STEAL; ioSteal = NULL; } SecondaryInventory = NULL; TSecondaryInventory = NULL; m_fadeDirection = Fade_stable; } else if(m_fadePosition >= 0) { m_fadePosition = 0; m_fadeDirection = Fade_stable; } } }
static void EntityEnteringCurrentZone2(Entity * io, ARX_PATH * current) { io->inzone_show = io->show; SendIOScriptEvent(NULL, io, SM_ENTERZONE, current->name); if(!current->controled.empty()) { EntityHandle t = entities.getById(current->controled); if(t != EntityHandle()) { ScriptParameters parameters; parameters.push_back(io->idString()); parameters.push_back(current->name); SendIOScriptEvent(NULL, entities[t], SM_CONTROLLEDZONE_ENTER, parameters); } } }
void StealIconGui::updateInput() { // steal if(player.Interface & INTER_STEAL) { if(m_rect.contains(Vec2f(DANAEMouse))) { eMouseState = MOUSE_IN_STEAL_ICON; cursorSetInteraction(); if(eeMouseDown1()) { ARX_INVENTORY_OpenClose(ioSteal); if(player.Interface & (INTER_INVENTORY | INTER_INVENTORYALL)) { ARX_SOUND_PlayInterface(SND_BACKPACK, Random::getf(0.9f, 1.1f)); } if(SecondaryInventory) { SendIOScriptEvent(entities.player(), ioSteal, SM_STEAL); bForceEscapeFreeLook = true; lOldTruePlayerMouseLook = !TRUE_PLAYER_MOUSELOOK_ON; } } if(DRAGINTER == NULL) { return; } } } }
void SecondaryInventoryCloseHudIcon::updateInput() { m_isSelected = m_rect.contains(Vec2f(DANAEMouse)); if(m_isSelected) { SpecialCursor=CURSOR_INTERACTION_ON; if(eeMouseDown1()) { Entity * io = NULL; if(SecondaryInventory) io = SecondaryInventory->io; else if(player.Interface & INTER_STEAL) io = ioSteal; if(io) { ARX_SOUND_PlayInterface(SND_BACKPACK, Random::getf(0.9f, 1.1f)); g_secondaryInventoryHud.m_fadeDirection = SecondaryInventoryHud::Fade_left; SendIOScriptEvent(io,SM_INVENTORY2_CLOSE); TSecondaryInventory=SecondaryInventory; SecondaryInventory=NULL; } } if(DRAGINTER == NULL) return; } }
void ARX_DAMAGES_DurabilityLoss(Entity * io, float loss) { if(!io) return; io->durability -= loss; if(io->durability <= 0) { SendIOScriptEvent(io, SM_BREAK); } }
void ARX_SCRIPT_AllowInterScriptExec() { ARX_PROFILE_FUNC(); // FIXME static local variable static long ppos = 0; if(arxtime.is_paused()) { return; } EVENT_SENDER = NULL; long heartbeat_count = std::min(long(entities.size()), 10l); for(long n = 0; n < heartbeat_count; n++) { EntityHandle i = EntityHandle(ppos++); if(i >= long(entities.size())){ ppos = 0; return; } if(entities[i] == NULL || !(entities[i]->gameFlags & GFLAG_ISINTREATZONE)) { continue; } if(!entities[i]->mainevent.empty()) { // Copy the even name to a local variable as it may change during execution // and cause unexpected behavior in SendIOScriptEvent std::string event = entities[i]->mainevent; SendIOScriptEvent(entities[i], SM_NULL, std::string(), event); } else { SendIOScriptEvent(entities[i], SM_MAIN); } } }
static void EntityEnteringCurrentZone(Entity * io, ARX_PATH * current) { io->inzone_show = io->show; if(JUST_RELOADED && (current->name == "ingot_maker" || current->name == "mauld_user")) { ARX_DEAD_CODE(); // TODO remove JUST_RELOADED global } else { SendIOScriptEvent(NULL, io, SM_ENTERZONE, current->name); if(!current->controled.empty()) { EntityHandle t = entities.getById(current->controled); if(t != EntityHandle()) { ScriptParameters parameters; parameters.push_back(io->idString()); parameters.push_back(current->name); SendIOScriptEvent(NULL, entities[t], SM_CONTROLLEDZONE_ENTER, parameters); } } } }
static void ARX_DAMAGES_IgnitIO(Entity * io, float dmg) { if(!io || (io->ioflags & IO_INVULNERABILITY)) return; if(io->ignition <= 0.f && io->ignition + dmg > 1.f) SendIOScriptEvent(io, SM_ENTERZONE, "cook_s"); if(io->ioflags & IO_FIX) io->ignition += dmg * ( 1.0f / 10 ); else if(io->ioflags & IO_ITEM) io->ignition += dmg * ( 1.0f / 8 ); else if(io->ioflags & IO_NPC) io->ignition += dmg * ( 1.0f / 4 ); }
void SecondaryInventoryHud::close() { Entity * io = NULL; if(SecondaryInventory) io = SecondaryInventory->io; else if(player.Interface & INTER_STEAL) io = ioSteal; if(io) { m_fadeDirection = Fade_left; SendIOScriptEvent(io, SM_INVENTORY2_CLOSE); TSecondaryInventory = SecondaryInventory; SecondaryInventory = NULL; } }
ScriptResult SendMsgToAllIO(ScriptMessage msg, const std::string & params) { ScriptResult ret = ACCEPT; for(size_t i = 0; i < entities.size(); i++) { const EntityHandle handle = EntityHandle(i); Entity * e = entities[handle]; if(e) { if(SendIOScriptEvent(e, msg, params) == REFUSE) { ret = REFUSE; } } } return ret; }
void SecondaryInventoryHud::update() { Entity * io = getSecondaryOrStealInvEntity(); if(io) { float dist = fdist(io->pos, player.pos + (Vec3f_Y_AXIS * 80.f)); float maxDist = player.m_telekinesis ? 900.f : 350.f; if(dist > maxDist) { if(m_fadeDirection != Fade_left) { ARX_SOUND_PlayInterface(SND_BACKPACK, Random::getf(0.9f, 1.1f)); m_fadeDirection = Fade_left; SendIOScriptEvent(io,SM_INVENTORY2_CLOSE); TSecondaryInventory=SecondaryInventory; SecondaryInventory=NULL; } else { if(player.Interface & INTER_STEAL) { player.Interface &= ~INTER_STEAL; } } } } else if(m_fadeDirection != Fade_left) { m_fadeDirection = Fade_left; } if(!(player.Interface & INTER_COMBATMODE) && (player.Interface & INTER_MINIBACK)) { // Pick All/Close Secondary Inventory if(TSecondaryInventory) { //These have to be calculated on each frame (to make them move). Rectf parent = Rectf(Vec2f(m_fadePosition, 0), m_defaultBackground->m_size.x * m_scale, m_defaultBackground->m_size.y * m_scale); m_pickAllButton.setScale(m_scale); m_closeButton.setScale(m_scale); m_pickAllButton.update(parent); m_closeButton.update(parent); } } }
void ARX_DAMAGES_ForceDeath(Entity * io_dead, Entity * io_killer) { if(io_dead->mainevent == "dead") { return; } Entity * old_sender = EVENT_SENDER; EVENT_SENDER = io_killer; if(io_dead == DRAGINTER) Set_DragInter(NULL); if(io_dead == FlyingOverIO) FlyingOverIO = NULL; if((MasterCamera.exist & 1) && (MasterCamera.io == io_dead)) MasterCamera.exist = 0; if((MasterCamera.exist & 2) && (MasterCamera.want_io == io_dead)) MasterCamera.exist = 0; lightHandleDestroy(io_dead->dynlight); lightHandleDestroy(io_dead->halo.dynlight); //Kill all speeches ARX_NPC_Behaviour_Reset(io_dead); ARX_SPEECH_ReleaseIOSpeech(io_dead); //Kill all Timers... ARX_SCRIPT_Timer_Clear_For_IO(io_dead); if(io_dead->mainevent != "dead") { if(SendIOScriptEvent(io_dead, SM_DIE) != REFUSE && ValidIOAddress(io_dead)) { io_dead->infracolor = Color3f::blue; } } if (!ValidIOAddress(io_dead)) return; ARX_SCRIPT_SetMainEvent(io_dead, "dead"); if(fartherThan(io_dead->pos, ACTIVECAM->orgTrans.pos, 3200.f)) { io_dead->animlayer[0].ctime = 9999999; io_dead->animBlend.lastanimtime = 0; } std::string killer; if(io_dead->ioflags & IO_NPC) io_dead->_npcdata->weaponinhand = 0; ARX_INTERACTIVE_DestroyDynamicInfo(io_dead); if(io_killer == entities.player()) { killer = "player"; } else { if(io_killer) killer = io_killer->idString(); } for(size_t i = 1; i < entities.size(); i++) { const EntityHandle handle = EntityHandle(i); Entity * ioo = entities[handle]; if(ioo == io_dead) continue; if(ioo && (ioo->ioflags & IO_NPC)) { if(ValidIONum(ioo->targetinfo)) if(entities[ioo->targetinfo] == io_dead) { EVENT_SENDER = io_dead; Stack_SendIOScriptEvent(entities[handle], SM_NULL, killer, "target_death"); ioo->targetinfo = EntityHandle(TARGET_NONE); ioo->_npcdata->reachedtarget = 0; } if(ValidIONum(ioo->_npcdata->pathfind.truetarget)) if(entities[ioo->_npcdata->pathfind.truetarget] == io_dead) { EVENT_SENDER = io_dead; Stack_SendIOScriptEvent(entities[handle], SM_NULL, killer, "target_death"); ioo->_npcdata->pathfind.truetarget = EntityHandle(TARGET_NONE); ioo->_npcdata->reachedtarget = 0; } } } io_dead->animlayer[1].cur_anim = NULL; io_dead->animlayer[2].cur_anim = NULL; io_dead->animlayer[3].cur_anim = NULL; if(io_dead->ioflags & IO_NPC) { io_dead->_npcdata->lifePool.current = 0; if(io_dead->_npcdata->weapon) { Entity * ioo = io_dead->_npcdata->weapon; if(ValidIOAddress(ioo)) { ioo->show = SHOW_FLAG_IN_SCENE; ioo->ioflags |= IO_NO_NPC_COLLIDE; ioo->pos = ioo->obj->vertexlist3[ioo->obj->origin].v; ioo->velocity = Vec3f(0.f, 13.f, 0.f); ioo->stopped = 0; } } } EVENT_SENDER = old_sender; }
void ARX_DAMAGES_DamageFIX(Entity * io, float dmg, EntityHandle source, bool isSpellHit) { if( !io || !io->show || !(io->ioflags & IO_FIX) || (io->ioflags & IO_INVULNERABILITY) || !io->script.data ) { return; } io->dmg_sum += dmg; if (ValidIONum(source)) EVENT_SENDER = entities[source]; else EVENT_SENDER = NULL; if(float(arxtime) > io->ouch_time + 500) { io->ouch_time = (unsigned long)(arxtime); char tex[32]; sprintf(tex, "%5.2f", io->dmg_sum); SendIOScriptEvent(io, SM_OUCH, tex); io->dmg_sum = 0.f; } if(rnd() * 100.f > io->durability) io->durability -= dmg * ( 1.0f / 2 ); //1.f; if(io->durability <= 0.f) { io->durability = 0.f; SendIOScriptEvent(io, SM_BREAK); } else { char dmm[32]; if(EVENT_SENDER == entities.player()) { if(isSpellHit) { sprintf(dmm, "%f spell", dmg); } else switch(ARX_EQUIPMENT_GetPlayerWeaponType()) { case WEAPON_BARE: sprintf(dmm, "%f bare", dmg); break; case WEAPON_DAGGER: sprintf(dmm, "%f dagger", dmg); break; case WEAPON_1H: sprintf(dmm, "%f 1h", dmg); break; case WEAPON_2H: sprintf(dmm, "%f 2h", dmg); break; case WEAPON_BOW: sprintf(dmm, "%f arrow", dmg); break; default: sprintf(dmm, "%f", dmg); break; } } else sprintf(dmm, "%f", dmg); if(SendIOScriptEvent(io, SM_HIT, dmm) != ACCEPT) return; } }
float ARX_DAMAGES_DamagePlayer(float dmg, DamageType type, EntityHandle source) { if (player.playerflags & PLAYERFLAGS_INVULNERABILITY) return 0; float damagesdone = 0.f; if(player.lifePool.current == 0.f) return damagesdone; if(dmg > player.lifePool.current) damagesdone = dmg; else damagesdone = player.lifePool.current; entities.player()->dmg_sum += dmg; if(float(arxtime) > entities.player()->ouch_time + 500) { Entity * oes = EVENT_SENDER; if(ValidIONum(source)) EVENT_SENDER = entities[source]; else EVENT_SENDER = NULL; entities.player()->ouch_time = (unsigned long)(arxtime); char tex[32]; sprintf(tex, "%5.2f", entities.player()->dmg_sum); SendIOScriptEvent( entities.player(), SM_OUCH, tex ); EVENT_SENDER = oes; float power = entities.player()->dmg_sum / player.lifePool.max * 220.f; AddQuakeFX(power * 3.5f, 500 + power * 3, rnd() * 100.f + power + 200, 0); entities.player()->dmg_sum = 0.f; } if(dmg > 0.f) { if(ValidIONum(source)) { Entity * pio = NULL; if(entities[source]->ioflags & IO_NPC) { pio = entities[source]->_npcdata->weapon; if(pio && (pio->poisonous == 0 || pio->poisonous_count == 0)) pio = NULL; } if(!pio) pio = entities[source]; if(pio && pio->poisonous && pio->poisonous_count != 0) { if(rnd() * 100.f > player.m_misc.resistPoison) { player.poison += pio->poisonous; } if(pio->poisonous_count != -1) pio->poisonous_count--; } } long alive; if(player.lifePool.current > 0) alive = 1; else alive = 0; if(!BLOCK_PLAYER_CONTROLS) player.lifePool.current -= dmg; if(player.lifePool.current <= 0.f) { player.lifePool.current = 0.f; if(alive) { //REFUSE_GAME_RETURN = 1; ARX_PLAYER_BecomesDead(); if((type & DAMAGE_TYPE_FIRE) || (type & DAMAGE_TYPE_FAKEFIRE)) { ARX_SOUND_PlayInterface(SND_PLAYER_DEATH_BY_FIRE); } SendIOScriptEvent(entities.player(), SM_DIE); for(size_t i = 1; i < entities.size(); i++) { const EntityHandle handle = EntityHandle(i); Entity * ioo = entities[handle]; if(ioo && (ioo->ioflags & IO_NPC)) { if(ioo->targetinfo == TARGET_PLAYER) { EVENT_SENDER = entities.player(); std::string killer; if(source == PlayerEntityHandle) { killer = "player"; } else if(source <= EntityHandle::Invalid) { killer = "none"; } else if(ValidIONum(source)) { killer = entities[source]->idString(); } SendIOScriptEvent(entities[handle], SM_NULL, killer, "target_death"); } } } } } if(player.lifePool.max <= 0.f) return damagesdone; float t = dmg / player.lifePool.max; if(Blood_Pos == 0.f) { Blood_Pos = 0.000001f; Blood_Duration = 100 + (t * 200.f); } else { long temp = t * 800.f; Blood_Duration += temp; } } // revient les barres ResetPlayerInterface(); return damagesdone; }
void SummonCreatureSpell::Update() { if(arxtime.is_paused()) return; float elapsed = arxtime.now_f() - m_timcreation; if(elapsed <= 4000) { if(Random::getf() > 0.7f) { Vec3f pos = m_fissure.m_eSrc; MakeCoolFx(pos); } m_fissure.Update(g_framedelay); m_fissure.Render(); m_requestSummon = true; m_summonedEntity = EntityHandle(); } else if(m_requestSummon) { lightHandleDestroy(m_light); m_requestSummon = false; ARX_SOUND_PlaySFX(SND_SPELL_ELECTRIC, &m_targetPos); Cylinder phys = Cylinder(m_targetPos, 50, -200); float anything = CheckAnythingInCylinder(phys, NULL, CFLAG_JUST_TEST); if(glm::abs(anything) < 30) { long tokeep; res::path cls; if(m_megaCheat) { if(Random::getf() > 0.5f) { tokeep = -1; cls = "graph/obj3d/interactive/npc/wrat_base/wrat_base"; } else { tokeep = 0; cls = "graph/obj3d/interactive/npc/y_mx/y_mx"; } } else if(Random::getf() > 0.997f || (sp_max && Random::getf() > 0.8f) || (cur_mr >= 3 && Random::getf() > 0.3f)) { tokeep = 0; cls = "graph/obj3d/interactive/npc/y_mx/y_mx"; } else if(Random::getf() > 0.997f || (cur_rf >= 3 && Random::getf() > 0.8f) || (cur_mr >= 3 && Random::getf() > 0.3f)) { tokeep = -1; cls = "graph/obj3d/interactive/npc/wrat_base/wrat_base"; } else if(m_level >= 9) { tokeep = 1; cls = "graph/obj3d/interactive/npc/demon/demon"; } else if(Random::getf() > 0.98f) { tokeep = -1; cls = "graph/obj3d/interactive/npc/wrat_base/wrat_base"; } else { tokeep = 0; cls = "graph/obj3d/interactive/npc/chicken_base/chicken_base"; } Entity * io = AddNPC(cls, -1, IO_IMMEDIATELOAD); if(!io) { cls = "graph/obj3d/interactive/npc/chicken_base/chicken_base"; tokeep = 0; io = AddNPC(cls, -1, IO_IMMEDIATELOAD); } if(io) { RestoreInitialIOStatusOfIO(io); io->summoner = m_caster; io->scriptload = 1; if(tokeep == 1) { io->ioflags |= IO_NOSAVE; } io->pos = phys.origin; SendInitScriptEvent(io); if(tokeep < 0) { io->scale=1.65f; io->physics.cyl.radius=25; io->physics.cyl.height=-43; io->speed_modif=1.f; } if(ValidIONum(m_caster)) { EVENT_SENDER = entities[m_caster]; } else { EVENT_SENDER = NULL; } SendIOScriptEvent(io,SM_SUMMONED); for(long j = 0; j < 3; j++) { Vec3f pos = m_fissure.m_eSrc; pos += randomVec3f() * 100.f; pos += Vec3f(-50.f, 50.f, -50.f); MakeCoolFx(pos); } if(tokeep==1) m_summonedEntity = io->index(); else m_summonedEntity = EntityHandle(); } } } else if(m_summonedEntity == EntityHandle()) { m_duration = 0; } }
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 ARX_PATH_UpdateAllZoneInOutInside() { arx_assert(entities.player()); static size_t count = 1; long f = glm::clamp(static_cast<long>(framedelay), 10l, 50l); if(count >= entities.size()) { count = 1; } if(entities.size() > 1) for(long tt = 0; tt < f; tt++) { const EntityHandle i = EntityHandle(count); Entity * io = entities[i]; if(count < entities.size() && io && io->ioflags & (IO_NPC | IO_ITEM) && io->show != SHOW_FLAG_MEGAHIDE ) { arx_assert(io->show != SHOW_FLAG_DESTROYED); ARX_PATH * p = ARX_PATH_CheckInZone(io); ARX_PATH * op = io->inzone; if(op == NULL && p == NULL) goto next; // Not in a zone if(op == p) { // Stayed inside Zone OP if(io->show != io->inzone_show) { io->inzone_show = io->show; goto entering; } } else if ((op != NULL) && (p == NULL)) // Leaving Zone OP { SendIOScriptEvent(io, SM_LEAVEZONE, op->name); if(!op->controled.empty()) { EntityHandle t = entities.getById(op->controled); if(t != EntityHandle::Invalid) { std::string str = io->idString() + ' ' + op->name; SendIOScriptEvent(entities[t], SM_CONTROLLEDZONE_LEAVE, str); } } } else if ((op == NULL) && (p != NULL)) // Entering Zone P { io->inzone_show = io->show; entering: if(JUST_RELOADED && (p->name == "ingot_maker" || p->name == "mauld_user")) { ARX_DEAD_CODE(); // TODO remove JUST_RELOADED global } else { SendIOScriptEvent(io, SM_ENTERZONE, p->name); if(!p->controled.empty()) { EntityHandle t = entities.getById(p->controled); if(t != EntityHandle::Invalid) { std::string params = io->idString() + ' ' + p->name; SendIOScriptEvent(entities[t], SM_CONTROLLEDZONE_ENTER, params); } } } } else { SendIOScriptEvent(io, SM_LEAVEZONE, op->name); if(!op->controled.empty()) { EntityHandle t = entities.getById(op->controled); if(t != EntityHandle::Invalid) { std::string str = io->idString() + ' ' + op->name; SendIOScriptEvent(entities[t], SM_CONTROLLEDZONE_LEAVE, str); } } io->inzone_show = io->show; SendIOScriptEvent(io, SM_ENTERZONE, p->name); if(!p->controled.empty()) { EntityHandle t = entities.getById(p->controled); if(t != EntityHandle::Invalid) { std::string str = io->idString() + ' ' + p->name; SendIOScriptEvent(entities[t], SM_CONTROLLEDZONE_ENTER, str); } } } io->inzone = p; } next: count++; if(count >= entities.size()) count = 1; } // player check************************************************* { ARX_PATH * p = ARX_PATH_CheckPlayerInZone(); ARX_PATH * op = player.inzone; if((op == NULL) && (p == NULL)) goto suite; // Not in a zone if(op == p) // Stayed inside Zone OP { } else if(op != NULL && p == NULL) // Leaving Zone OP { SendIOScriptEvent(entities.player(), SM_LEAVEZONE, op->name); CHANGE_LEVEL_ICON = -1; if(!op->controled.empty()) { EntityHandle t = entities.getById(op->controled); if(t != EntityHandle::Invalid) { SendIOScriptEvent(entities[t], SM_CONTROLLEDZONE_LEAVE, "player " + op->name); } } } else if ((op == NULL) && (p != NULL)) // Entering Zone P { SendIOScriptEvent(entities.player(), SM_ENTERZONE, p->name); if(p->flags & PATH_AMBIANCE && !p->ambiance.empty()) ARX_SOUND_PlayZoneAmbiance(p->ambiance, ARX_SOUND_PLAY_LOOPED, p->amb_max_vol * ( 1.0f / 100 )); if(p->flags & PATH_FARCLIP) { desired.flags |= GMOD_ZCLIP; desired.zclip = p->farclip; } if (p->flags & PATH_REVERB) { } if(p->flags & PATH_RGB) { desired.flags |= GMOD_DCOLOR; desired.depthcolor = p->rgb; } if(!p->controled.empty()) { EntityHandle t = entities.getById(p->controled); if(t != EntityHandle::Invalid) { SendIOScriptEvent(entities[t], SM_CONTROLLEDZONE_ENTER, "player " + p->name); } } } else { if(!op->controled.empty()) { EntityHandle t = entities.getById(op->controled); if(t != EntityHandle::Invalid) { SendIOScriptEvent(entities[t], SM_CONTROLLEDZONE_LEAVE, "player " + p->name); } } if(!op->controled.empty()) { EntityHandle t = entities.getById(p->controled); if(t != EntityHandle::Invalid) { SendIOScriptEvent(entities[t], SM_CONTROLLEDZONE_ENTER, "player " + p->name); } } } player.inzone = p; } suite: JUST_RELOADED = 0; }
void TreatBackgroundDynlights() { ARX_PROFILE_FUNC(); for(size_t i = 0; i < g_staticLightsMax; i++) { EERIE_LIGHT * light = g_staticLights[i]; if(light && (light->extras & EXTRAS_SEMIDYNAMIC)) { float fMaxdist = player.m_telekinesis ? 850 : 300; if(!fartherThan(light->pos, g_camera->m_pos, fMaxdist)) { ComputeLight2DPos(light); } else { light->m_screenRect = Rectf(1, 0, -1, 0); // Intentionally invalid } if(!light->m_ignitionStatus) { // just extinguished EERIE_LIGHT * dynLight = lightHandleGet(light->m_ignitionLightHandle); if(dynLight) { dynLight->m_exists = false; light->m_ignitionLightHandle = LightHandle(); for(size_t l = 0; l < entities.size(); l++) { const EntityHandle handle = EntityHandle(l); Entity * e = entities[handle]; if(e && (e->ioflags & IO_MARKER)) { Vec3f _pos2 = GetItemWorldPosition(e); if(!fartherThan(light->pos, _pos2, 300.f)) { SendIOScriptEvent(NULL, e, SM_CUSTOM, "douse"); } } } } } else { // just light up if(!lightHandleGet(light->m_ignitionLightHandle)) { for(size_t l = 0; l < entities.size(); l++) { const EntityHandle handle = EntityHandle(l); Entity * e = entities[handle]; if(e && (e->ioflags & IO_MARKER)) { Vec3f _pos2 = GetItemWorldPosition(e); if(!fartherThan(light->pos, _pos2, 300.f)) { SendIOScriptEvent(NULL, e, SM_CUSTOM, "fire"); } } } light->m_ignitionLightHandle = GetFreeDynLight(); } EERIE_LIGHT * dynamicLight = lightHandleGet(light->m_ignitionLightHandle); if(dynamicLight) { dynamicLight->pos = light->pos; dynamicLight->fallstart = light->fallstart; dynamicLight->fallend = light->fallend; dynamicLight->m_isIgnitionLight = true; dynamicLight->intensity = light->intensity; dynamicLight->ex_flaresize = light->ex_flaresize; dynamicLight->extras = light->extras; dynamicLight->duration = GameDurationMs(std::numeric_limits<long>::max()); dynamicLight->rgb = light->rgb - light->rgb * light->ex_flicker * randomColor3f() * 0.5f; dynamicLight->rgb = componentwise_max(dynamicLight->rgb, Color3f::black); RecalcLight(dynamicLight); } } } } for(size_t i = 0; i < g_dynamicLightsMax; i++) { EERIE_LIGHT * el = &g_dynamicLights[i]; if(el->m_exists && el->duration != 0) { const GameDuration elapsed = g_gameTime.now() - el->creationTime; const GameDuration duration = el->duration; if(elapsed >= duration) { float sub = g_gameTime.lastFrameDuration() / GameDurationMs(1000); el->rgb.r -= sub; el->rgb.g -= sub; el->rgb.b -= sub; if(el->rgb.r < 0) el->rgb.r = 0.f; if(el->rgb.g < 0) el->rgb.g = 0.f; if(el->rgb.b < 0) el->rgb.b = 0.f; if(el->rgb.r + el->rgb.g + el->rgb.b == 0) { el->m_exists = false; el->duration = 0; } } } } }
void ManageCombatModeAnimations() { arx_assert(entities.player()); 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]); AimTime = 0; } } switch(weapontype) { case WEAPON_BARE: // BARE HANDS PLAYER MANAGEMENT if(layer1.cur_anim == alist[ANIM_BARE_WAIT]) { AimTime = 0; if(eeMousePressed1()) { changeAnimation(io, 1, alist[ANIM_BARE_STRIKE_LEFT_START + CurrFightPos * 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); AimTime = (unsigned long)(arxtime); } 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(io, SM_STRIKE, "bare"); PlayerWeaponBlocked = -1; CurrFightPos = 0; 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); CurrFightPos = 0; AimTime = (unsigned long)(arxtime); PlayerWeaponBlocked = -1; } else if(layer1.ctime > layer1.cur_anim->anims[layer1.altidx_cur]->anim_time * 0.2f && layer1.ctime < layer1.cur_anim->anims[layer1.altidx_cur]->anim_time * 0.8f && PlayerWeaponBlocked == -1 ) { long id = -1; 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 != -1) { Sphere sphere; sphere.origin = io->obj->vertexlist3[id].v; sphere.radius = 25.f; EntityHandle num; if(CheckAnythingInSphere(sphere, PlayerEntityHandle, 0, &num)) { float dmgs = (player.m_miscFull.damages + 1) * STRIKE_AIMTIME; if(ARX_DAMAGES_TryToDoDamage(io->obj->vertexlist3[id].v, dmgs, 40, PlayerEntityHandle)) { PlayerWeaponBlocked = layer1.ctime; } ARX_PARTICLES_Spawn_Spark(sphere.origin, int(dmgs), 2); if(ValidIONum(num)) { ARX_SOUND_PlayCollision(entities[num]->material, MATERIAL_FLESH, 1.f, 1.f, sphere.origin, NULL); } } } } } } break; case WEAPON_DAGGER: // DAGGER PLAYER MANAGEMENT // Waiting and receiving Strike Impulse if(layer1.cur_anim == alist[ANIM_DAGGER_WAIT]) { AimTime = 0; if(eeMousePressed1()) { changeAnimation(io, 1, alist[ANIM_DAGGER_STRIKE_LEFT_START + CurrFightPos * 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); AimTime = (unsigned long)(arxtime); } 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(io, SM_STRIKE, "dagger"); CurrFightPos = 0; AimTime = 0; } else if(layer1.cur_anim == alist[ANIM_DAGGER_STRIKE_LEFT+j*3]) { if(layer1.ctime > layer1.cur_anim->anims[layer1.altidx_cur]->anim_time * 0.3f && layer1.ctime < layer1.cur_anim->anims[layer1.altidx_cur]->anim_time * 0.7f) { Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]]; if(PlayerWeaponBlocked == -1 && ARX_EQUIPMENT_Strike_Check(io, weapon, STRIKE_AIMTIME, 0)) { PlayerWeaponBlocked = layer1.ctime; } } if(layer1.flags & EA_ANIMEND) { changeAnimation(io, 1, alist[ANIM_DAGGER_WAIT], EA_LOOP); layer1.flags &= ~(EA_PAUSED | EA_REVERSE); CurrFightPos = 0; AimTime = (unsigned long)(arxtime); PlayerWeaponBlocked = -1; } if(PlayerWeaponBlocked != -1 && layer1.ctime < layer1.cur_anim->anims[layer1.altidx_cur]->anim_time * 0.9f) { Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]]; ARX_EQUIPMENT_Strike_Check(io, weapon, STRIKE_AIMTIME, 1); } } } break; case WEAPON_1H: // 1HANDED PLAYER MANAGEMENT // Waiting and Received Strike Impulse if(layer1.cur_anim == alist[ANIM_1H_WAIT]) { AimTime = 0; if(eeMousePressed1()) { changeAnimation(io, 1, alist[ANIM_1H_STRIKE_LEFT_START + CurrFightPos * 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); AimTime = (unsigned long)(arxtime); } 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(io, SM_STRIKE, "1h"); CurrFightPos = 0; AimTime = 0; } else if(layer1.cur_anim == alist[ANIM_1H_STRIKE_LEFT+j*3]) { if(layer1.ctime > layer1.cur_anim->anims[layer1.altidx_cur]->anim_time * 0.3f && layer1.ctime < layer1.cur_anim->anims[layer1.altidx_cur]->anim_time * 0.7f) { Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]]; if(PlayerWeaponBlocked == -1 && ARX_EQUIPMENT_Strike_Check(io, weapon, STRIKE_AIMTIME, 0)) { PlayerWeaponBlocked = layer1.ctime; } } if(layer1.flags & EA_ANIMEND) { changeAnimation(io, 1, alist[ANIM_1H_WAIT], EA_LOOP); layer1.flags &= ~(EA_PAUSED | EA_REVERSE); CurrFightPos = 0; AimTime = 0; PlayerWeaponBlocked = -1; } if(PlayerWeaponBlocked != -1 && layer1.ctime < layer1.cur_anim->anims[layer1.altidx_cur]->anim_time * 0.9f) { Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]]; ARX_EQUIPMENT_Strike_Check(io, weapon, STRIKE_AIMTIME, 1); } } } break; case WEAPON_2H: // 2HANDED PLAYER MANAGEMENT // Waiting and Receiving Strike Impulse if(layer1.cur_anim == alist[ANIM_2H_WAIT]) { AimTime = 0; if(eeMousePressed1()) { changeAnimation(io, 1, alist[ANIM_2H_STRIKE_LEFT_START + CurrFightPos * 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); AimTime = (unsigned long)(arxtime); } 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(io, SM_STRIKE, "2h"); CurrFightPos = 0; AimTime = 0; } else if(layer1.cur_anim == alist[ANIM_2H_STRIKE_LEFT+j*3]) { if(layer1.ctime > layer1.cur_anim->anims[layer1.altidx_cur]->anim_time * 0.3f && layer1.ctime < layer1.cur_anim->anims[layer1.altidx_cur]->anim_time * 0.7f) { Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]]; if(PlayerWeaponBlocked == -1 && ARX_EQUIPMENT_Strike_Check(io, weapon, STRIKE_AIMTIME, 0)) { PlayerWeaponBlocked = layer1.ctime; } } if(layer1.flags & EA_ANIMEND) { changeAnimation(io, 1, alist[ANIM_2H_WAIT], EA_LOOP); layer1.flags &= ~(EA_PAUSED | EA_REVERSE); CurrFightPos = 0; AimTime = 0; PlayerWeaponBlocked = -1; } if(PlayerWeaponBlocked != -1 && layer1.ctime < layer1.cur_anim->anims[layer1.altidx_cur]->anim_time * 0.9f) { Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]]; ARX_EQUIPMENT_Strike_Check(io, weapon, STRIKE_AIMTIME, 1); } } } break; case WEAPON_BOW: // MISSILE PLAYER MANAGEMENT if(layer1.cur_anim == alist[ANIM_MISSILE_STRIKE_CYCLE]) { if(GLOBAL_SLOWDOWN != 1.f) BOW_FOCAL += Original_framedelay; else BOW_FOCAL += framedelay; if(BOW_FOCAL > 710) BOW_FOCAL = 710; } // Waiting and Receiving Strike Impulse if(layer1.cur_anim == alist[ANIM_MISSILE_WAIT]) { AimTime = (unsigned long)(arxtime); 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)) { 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); AimTime = (unsigned long)(arxtime); } 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(io, SM_STRIKE, "bow"); StrikeAimtime(); STRIKE_AIMTIME = (float)(BOW_FOCAL)/710.f; 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 = STRIKE_AIMTIME; 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 >= 0) { orgPos = io->obj->vertexlist3[io->obj->fastaccess.left_attach].v; } 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.setYaw(player.angle.getYaw()); angle.setPitch(player.angle.getPitch() + 8); angle.setRoll(player.angle.getRoll()); PlayerLaunchArrow_Test(aimratio, poisonous, pos, angle); angle.setYaw(player.angle.getYaw()); angle.setPitch(player.angle.getPitch() - 8); PlayerLaunchArrow_Test(aimratio, poisonous, pos, angle); angle.setYaw(player.angle.getYaw()); angle.setPitch(player.angle.getPitch() + 4.f); PlayerLaunchArrow_Test(aimratio, poisonous, pos, angle); angle.setYaw(player.angle.getYaw()); angle.setPitch(player.angle.getPitch() - 4.f); PlayerLaunchArrow_Test(aimratio, poisonous, pos, angle); } AimTime = 0; } else if(layer1.cur_anim == alist[ANIM_MISSILE_STRIKE]) { BOW_FOCAL -= Original_framedelay; if(BOW_FOCAL < 0) BOW_FOCAL = 0; if(layer1.flags & EA_ANIMEND) { BOW_FOCAL = 0; changeAnimation(io, 1, alist[ANIM_MISSILE_WAIT], EA_LOOP); AimTime = 0; PlayerWeaponBlocked = -1; EERIE_LINKEDOBJ_UnLinkObjectFromObject(io->obj, arrowobj); } } break; } LAST_WEAPON_TYPE = weapontype; }
void ARX_PATH_UpdateAllZoneInOutInside() { ARX_PROFILE_FUNC(); arx_assert(entities.player()); static size_t count = 1; long f = glm::clamp(static_cast<long>(g_framedelay), 10l, 50l); if(count >= entities.size()) { count = 1; } if(entities.size() > 1) { for(long tt = 0; tt < f; tt++) { const EntityHandle i = EntityHandle(count); Entity * io = entities[i]; if( count < entities.size() && io && io->ioflags & (IO_NPC | IO_ITEM) && io->show != SHOW_FLAG_MEGAHIDE ) { arx_assert(io->show != SHOW_FLAG_DESTROYED); ARX_PATH * current = ARX_PATH_CheckInZone(io); ARX_PATH * last = io->inzone; if(!last && !current) { // Not in a zone } else if(last == current) { // Stayed inside last zone if(io->show != io->inzone_show) { EntityEnteringCurrentZone(io, current); } } else if(last && !current) { // Leaving last zone EntityLeavingLastZone(io, last); } else if(!last) { // Entering current zone EntityEnteringCurrentZone(io, current); } else { // Changed from last to current zone EntityLeavingLastZone(io, last); EntityEnteringCurrentZone2(io, current); } io->inzone = current; } count++; if(count >= entities.size()) count = 1; } } // player check************************************************* { ARX_PATH * current = ARX_PATH_CheckPlayerInZone(); ARX_PATH * last = player.inzone; if(!last && !current) { // Not in a zone } else if(last == current) { // Stayed inside last zone } else if(last && !current) { // Leaving last zone SendIOScriptEvent(NULL, entities.player(), SM_LEAVEZONE, last->name); CHANGE_LEVEL_ICON = NoChangeLevel; if(!last->controled.empty()) { EntityHandle t = entities.getById(last->controled); if(t != EntityHandle()) { ScriptParameters parameters; parameters.push_back("player"); parameters.push_back(last->name); SendIOScriptEvent(NULL, entities[t], SM_CONTROLLEDZONE_LEAVE, parameters); } } } else if(!last) { // Entering current zone SendIOScriptEvent(NULL, entities.player(), SM_ENTERZONE, current->name); if(current->flags & PATH_AMBIANCE && !current->ambiance.empty()) { ARX_SOUND_PlayZoneAmbiance(current->ambiance, ARX_SOUND_PLAY_LOOPED, current->amb_max_vol * 0.01f); } if(current->flags & PATH_FARCLIP) { g_desiredFogParameters.flags |= GMOD_ZCLIP; g_desiredFogParameters.zclip = current->farclip; } if(current->flags & PATH_RGB) { g_desiredFogParameters.flags |= GMOD_DCOLOR; g_desiredFogParameters.depthcolor = current->rgb; } if(!current->controled.empty()) { EntityHandle t = entities.getById(current->controled); if(t != EntityHandle()) { ScriptParameters parameters; parameters.push_back("player"); parameters.push_back(current->name); SendIOScriptEvent(NULL, entities[t], SM_CONTROLLEDZONE_ENTER, parameters); } } } else { // Changed from last to current zone if(!last->controled.empty()) { EntityHandle t = entities.getById(last->controled); if(t != EntityHandle()) { ScriptParameters parameters; parameters.push_back("player"); parameters.push_back(last->name); SendIOScriptEvent(NULL, entities[t], SM_CONTROLLEDZONE_LEAVE, parameters); } } if(!last->controled.empty()) { EntityHandle t = entities.getById(current->controled); if(t != EntityHandle()) { ScriptParameters parameters; parameters.push_back("player"); parameters.push_back(current->name); SendIOScriptEvent(NULL, entities[t], SM_CONTROLLEDZONE_ENTER, parameters); } } } player.inzone = current; } JUST_RELOADED = 0; }
void RiseDeadSpell::Update(float timeDelta) { if(m_creationFailed) { m_light = LightHandle(); return; } m_duration+=200; m_fissure.Update(timeDelta); m_fissure.Render(); if(lightHandleIsValid(m_light)) { EERIE_LIGHT * light = lightHandleGet(m_light); light->intensity = 0.7f + 2.3f; light->fallend = 500.f; light->fallstart = 400.f; light->rgb = Color3f(0.8f, 0.2f, 0.2f); light->duration=800; light->time_creation = (unsigned long)(arxtime); } unsigned long tim = m_fissure.ulCurrentTime; if(tim > 3000 && m_entity == EntityHandle() && !m_creationFailed) { ARX_SOUND_PlaySFX(SND_SPELL_ELECTRIC, &m_targetPos); Cylinder phys = Cylinder(m_targetPos, 50, -200); float anything = CheckAnythingInCylinder(phys, NULL, CFLAG_JUST_TEST); if(glm::abs(anything) < 30) { const char * cls = "graph/obj3d/interactive/npc/undead_base/undead_base"; Entity * io = AddNPC(cls, -1, IO_IMMEDIATELOAD); if(io) { ARX_INTERACTIVE_HideGore(io); RestoreInitialIOStatusOfIO(io); io->summoner = m_caster; io->ioflags|=IO_NOSAVE; m_entity = io->index(); io->scriptload=1; ARX_INTERACTIVE_Teleport(io, phys.origin); SendInitScriptEvent(io); if(ValidIONum(m_caster)) { EVENT_SENDER = entities[m_caster]; } else { EVENT_SENDER = NULL; } SendIOScriptEvent(io,SM_SUMMONED); Vec3f pos = m_fissure.m_eSrc; pos += randomVec3f() * 100.f; pos += Vec3f(-50.f, 50.f, -50.f); MakeCoolFx(pos); } m_light = LightHandle(); } else { ARX_SOUND_PlaySFX(SND_MAGIC_FIZZLE); m_creationFailed = true; m_duration=0; } } else if(!arxtime.is_paused() && tim < 4000) { if(Random::getf() > 0.95f) { MakeCoolFx(m_fissure.m_eSrc); } } }
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 TreatBackgroundDynlights() { long n; for (size_t i = 0; i < MAX_LIGHTS; i++) { if ((GLight[i] != NULL) && (GLight[i]->extras & EXTRAS_SEMIDYNAMIC)) { float fMaxdist = 300; if (Project.telekinesis) fMaxdist = 850; if(!fartherThan(GLight[i]->pos, ACTIVECAM->pos, fMaxdist)) { ComputeLight2DPos(GLight[i]); } if (GLight[i]->status == 0) { // vient de s'éteindre if (GLight[i]->tl > 0) { DynLight[GLight[i]->tl].exist = 0; GLight[i]->tl = -1; Vec3f _pos2; for (long l = 0; l < inter.nbmax; l++) { if ((inter.iobj[l] != NULL) && (inter.iobj[l]->ioflags & IO_MARKER)) { GetItemWorldPosition(inter.iobj[l], &_pos2); if(!fartherThan(GLight[i]->pos, _pos2, 300.f)) { SendIOScriptEvent(inter.iobj[l], SM_CUSTOM, "douse"); } } } } } else { // vient de s'allumer if (GLight[i]->tl <= 0) { Vec3f _pos2; for (long l = 0; l < inter.nbmax; l++) { if ((inter.iobj[l] != NULL) && (inter.iobj[l]->ioflags & IO_MARKER)) { GetItemWorldPosition(inter.iobj[l], &_pos2); if(!fartherThan(GLight[i]->pos, _pos2, 300.f)) { SendIOScriptEvent(inter.iobj[l], SM_CUSTOM, "fire"); } } } GLight[i]->tl = GetFreeDynLight(); } n = GLight[i]->tl; if (n != -1) { DynLight[n].pos.x = GLight[i]->pos.x; DynLight[n].pos.y = GLight[i]->pos.y; DynLight[n].pos.z = GLight[i]->pos.z; DynLight[n].exist = 1; DynLight[n].fallstart = GLight[i]->fallstart; DynLight[n].fallend = GLight[i]->fallend; DynLight[n].type = TYP_SPECIAL1; DynLight[n].intensity = GLight[i]->intensity; DynLight[n].ex_flaresize = GLight[i]->ex_flaresize; DynLight[n].extras = GLight[i]->extras; DynLight[n].duration = std::numeric_limits<long>::max(); DynLight[n].rgb.r = GLight[i]->rgb.r - GLight[i]->rgb.r * GLight[i]->ex_flicker.r * rnd() * ( 1.0f / 2 ); DynLight[n].rgb.g = GLight[i]->rgb.g - GLight[i]->rgb.g * GLight[i]->ex_flicker.g * rnd() * ( 1.0f / 2 ); DynLight[n].rgb.b = GLight[i]->rgb.b - GLight[i]->rgb.b * GLight[i]->ex_flicker.b * rnd() * ( 1.0f / 2 ); if (DynLight[n].rgb.r < 0.f) DynLight[n].rgb.r = 0.f; if (DynLight[n].rgb.g < 0.f) DynLight[n].rgb.g = 0.f; if (DynLight[n].rgb.b < 0.f) DynLight[n].rgb.b = 0.f; DynLight[n].rgb255.r = DynLight[n].rgb.r * 255.f; DynLight[n].rgb255.g = DynLight[n].rgb.g * 255.f; DynLight[n].rgb255.b = DynLight[n].rgb.b * 255.f; DynLight[n].falldiff = DynLight[n].fallend - DynLight[n].fallstart; DynLight[n].falldiffmul = 1.f / DynLight[n].falldiff; DynLight[n].precalc = DynLight[n].intensity * GLOBAL_LIGHT_FACTOR; } } } } }
static float ARX_THROWN_ComputeDamages(long thrownum, EntityHandle source, EntityHandle target) { float distance_limit = 1000.f; Entity * io_target = entities[target]; Entity * io_source = entities[source]; SendIOScriptEvent(io_target, SM_AGGRESSION); float distance = fdist(Thrown[thrownum].position, Thrown[thrownum].initial_position); float distance_modifier = 1.f; if(distance < distance_limit * 2.f) { distance_modifier = distance / distance_limit; if(distance_modifier < 0.5f) distance_modifier = 0.5f; } else { distance_modifier = 2.f; } float attack, dmgs, backstab, ac; backstab = 1.f; bool critical = false; if(source == 0) { attack = Thrown[thrownum].damages; if(Random::getf(0.f, 100.f) <= float(player.m_attributeFull.dexterity - 9) * 2.f + float(player.m_skillFull.projectile * 0.2f)) { if(SendIOScriptEvent(io_source, SM_CRITICAL, "bow") != REFUSE) critical = true; } dmgs = attack; if(io_target->_npcdata->npcflags & NPCFLAG_BACKSTAB) { if(Random::getf(0.f, 100.f) <= player.m_skillFull.stealth) { if(SendIOScriptEvent(io_source, SM_BACKSTAB, "bow") != REFUSE) backstab = 1.5f; } } } else { // TODO treat NPC !!! ARX_DEAD_CODE(); attack = 0; dmgs = 0; } float absorb; if(target == 0) { ac = player.m_miscFull.armorClass; absorb = player.m_skillFull.defense * .5f; } else { ac = ARX_INTERACTIVE_GetArmorClass(io_target); absorb = io_target->_npcdata->absorb; } char wmat[64]; std::string _amat = "flesh"; const std::string * amat = &_amat; strcpy(wmat, "dagger"); if(!io_target->armormaterial.empty()) { amat = &io_target->armormaterial; } if(io_target == entities.player()) { if(ValidIONum(player.equiped[EQUIP_SLOT_ARMOR])) { Entity * io = entities[player.equiped[EQUIP_SLOT_ARMOR]]; if(io && !io->armormaterial.empty()) { amat = &io->armormaterial; } } } float power; power = dmgs * ( 1.0f / 20 ); if(power > 1.f) power = 1.f; power = power * 0.15f + 0.85f; ARX_SOUND_PlayCollision(*amat, wmat, power, 1.f, Thrown[thrownum].position, io_source); dmgs *= backstab; dmgs -= dmgs * (absorb * ( 1.0f / 100 )); float chance = 100.f - (ac - attack); float dice = Random::getf(0.f, 100.f); if(dice <= chance) { if(dmgs > 0.f) { if(critical) dmgs *= 1.5f; dmgs *= distance_modifier; return dmgs; } } return 0.f; }
float ARX_EQUIPMENT_ComputeDamages(Entity * io_source, Entity * io_target, float ratioaim, Vec3f * position) { EVENT_SENDER = io_source; SendIOScriptEvent(io_target, SM_AGGRESSION); if(!io_source || !io_target) return 0.f; if(!(io_target->ioflags & IO_NPC)) { if(io_target->ioflags & IO_FIX) { if (io_source == entities.player()) ARX_DAMAGES_DamageFIX(io_target, player.m_miscFull.damages, PlayerEntityHandle, false); else if (io_source->ioflags & IO_NPC) ARX_DAMAGES_DamageFIX(io_target, io_source->_npcdata->damages, io_source->index(), false); else ARX_DAMAGES_DamageFIX(io_target, 1, io_source->index(), false); } return 0.f; } float attack, ac, damages; float backstab = 1.f; std::string _wmat = "bare"; const std::string * wmat = &_wmat; std::string _amat = "flesh"; const std::string * amat = &_amat; bool critical = false; if(io_source == entities.player()) { if(ValidIONum(player.equiped[EQUIP_SLOT_WEAPON])) { Entity * io = entities[player.equiped[EQUIP_SLOT_WEAPON]]; if(io && !io->weaponmaterial.empty()) { wmat = &io->weaponmaterial; } } attack = player.m_miscFull.damages; if(Random::getf(0.f, 100.f) <= player.m_miscFull.criticalHit) { if(SendIOScriptEvent(io_source, SM_CRITICAL) != REFUSE) critical = true; } else critical = false; damages = attack * ratioaim; if(io_target->_npcdata->npcflags & NPCFLAG_BACKSTAB) { if(Random::getf(0.f, 100.f) <= player.m_skillFull.stealth * ( 1.0f / 2 )) { if(SendIOScriptEvent(io_source, SM_BACKSTAB) != REFUSE) backstab = 1.5f; } } } else { if(!(io_source->ioflags & IO_NPC)) // no NPC source... return 0.f; if(!io_source->weaponmaterial.empty()) { wmat = &io_source->weaponmaterial; } if(io_source->_npcdata->weapon) { Entity * iow = io_source->_npcdata->weapon; if(!iow->weaponmaterial.empty()) { wmat = &iow->weaponmaterial; } } attack = io_source->_npcdata->tohit; damages = io_source->_npcdata->damages * ratioaim * Random::getf(0.5f, 1.0f); SpellBase * spell = spells.getSpellOnTarget(io_source->index(), SPELL_CURSE); if(spell) { damages *= (1 - spell->m_level * 0.05f); } if(Random::getf(0.f, 100) <= io_source->_npcdata->critical) { if(SendIOScriptEvent(io_source, SM_CRITICAL) != REFUSE) critical = true; } else critical = false; if(Random::getf(0.f, 100.f) <= (float)io_source->_npcdata->backstab_skill) { if(SendIOScriptEvent(io_source, SM_BACKSTAB) != REFUSE) backstab = 1.5f; } } float absorb; if(io_target == entities.player()) { ac = player.m_miscFull.armorClass; absorb = player.m_skillFull.defense * ( 1.0f / 2 ); } else { ac = ARX_INTERACTIVE_GetArmorClass(io_target); absorb = io_target->_npcdata->absorb; SpellBase * spell = spells.getSpellOnTarget(io_target->index(), SPELL_CURSE); if(spell) { float modif = (1 - spell->m_level * 0.05f); ac *= modif; absorb *= modif; } } if(!io_target->armormaterial.empty()) { amat = &io_target->armormaterial; } if(io_target == entities.player()) { if(ValidIONum(player.equiped[EQUIP_SLOT_ARMOR])) { Entity * io = entities[player.equiped[EQUIP_SLOT_ARMOR]]; if(io && !io->armormaterial.empty()) { amat = &io->armormaterial; } } } float dmgs = damages * backstab; dmgs -= dmgs * absorb * 0.01f; Vec3f pos = io_target->pos; float power = std::min(1.f, dmgs * 0.05f) * 0.1f + 0.9f; ARX_SOUND_PlayCollision(*amat, *wmat, power, 1.f, pos, io_source); float chance = 100.f - (ac - attack); if(Random::getf(0.f, 100.f) > chance) { return 0.f; } ARX_SOUND_PlayCollision("flesh", *wmat, power, 1.f, pos, io_source); if(dmgs > 0.f) { if(critical) { dmgs *= 1.5f; } if(io_target == entities.player()) { // TODO should this be player.pos - player.baseOffset() = player.basePosition()? Vec3f ppos = io_source->pos - (player.pos + player.baseOffset()); ppos = glm::normalize(ppos); // Push the player PUSH_PLAYER_FORCE += ppos * -dmgs * Vec3f(1.0f / 11, 1.0f / 30, 1.0f / 11); ARX_DAMAGES_DamagePlayer(dmgs, 0, io_source->index()); ARX_DAMAGES_DamagePlayerEquipment(dmgs); } else { Vec3f ppos = io_source->pos - io_target->pos; ppos = glm::normalize(ppos); // Push the NPC io_target->forcedmove += ppos * -dmgs; Vec3f * pos = position ? position : &io_target->pos; ARX_DAMAGES_DamageNPC(io_target, dmgs, io_source->index(), false, pos); } } return dmgs; }
//************************************************************************************* // flags & 1 == spell damage //************************************************************************************* float ARX_DAMAGES_DamageNPC(Entity * io, float dmg, EntityHandle source, bool isSpellHit, const Vec3f * pos) { if( !io || !io->show || !(io->ioflags & IO_NPC) || (io->ioflags & IO_INVULNERABILITY) ) { return 0.f; } float damagesdone = 0.f; if(io->_npcdata->lifePool.current <= 0.f) { if(source != PlayerEntityHandle || (source == PlayerEntityHandle && player.equiped[EQUIP_SLOT_WEAPON] > 0)) { if(dmg >= io->_npcdata->lifePool.max * 0.4f && pos) ARX_NPC_TryToCutSomething(io, pos); return damagesdone; } return damagesdone; } io->dmg_sum += dmg; if(float(arxtime) > io->ouch_time + 500) { if(ValidIONum(source)) EVENT_SENDER = entities[source]; else EVENT_SENDER = NULL; io->ouch_time = (unsigned long)(arxtime); char tex[32]; if(EVENT_SENDER && EVENT_SENDER->summoner == 0) { EVENT_SENDER = entities.player(); sprintf(tex, "%5.2f summoned", io->dmg_sum); } else { sprintf(tex, "%5.2f", io->dmg_sum); } SendIOScriptEvent(io, SM_OUCH, tex); io->dmg_sum = 0.f; spells.endByTarget(io->index(), SPELL_CONFUSE); } if(dmg >= 0.f) { if(ValidIONum(source)) { Entity * pio = NULL; if(source == 0) { if(player.equiped[EQUIP_SLOT_WEAPON] != PlayerEntityHandle && ValidIONum(player.equiped[EQUIP_SLOT_WEAPON])) { pio = entities[player.equiped[EQUIP_SLOT_WEAPON]]; if((pio && (pio->poisonous == 0 || pio->poisonous_count == 0)) || isSpellHit) { pio = NULL; } } } else { if(entities[source]->ioflags & IO_NPC) { pio = entities[source]->_npcdata->weapon; if(pio && (pio->poisonous == 0 || pio->poisonous_count == 0)) { pio = NULL; } } } if(!pio) pio = entities[source]; if(pio && pio->poisonous && (pio->poisonous_count != 0)) { if(rnd() * 100.f > io->_npcdata->resist_poison) { io->_npcdata->poisonned += pio->poisonous; } if (pio->poisonous_count != -1) pio->poisonous_count--; } } if(io->script.data != NULL) { if(source >= PlayerEntityHandle) { if(ValidIONum(source)) EVENT_SENDER = entities[source]; else EVENT_SENDER = NULL; char dmm[256]; if(EVENT_SENDER == entities.player()) { if(isSpellHit) { sprintf(dmm, "%f spell", dmg); } else switch (ARX_EQUIPMENT_GetPlayerWeaponType()) { case WEAPON_BARE: sprintf(dmm, "%f bare", dmg); break; case WEAPON_DAGGER: sprintf(dmm, "%f dagger", dmg); break; case WEAPON_1H: sprintf(dmm, "%f 1h", dmg); break; case WEAPON_2H: sprintf(dmm, "%f 2h", dmg); break; case WEAPON_BOW: sprintf(dmm, "%f arrow", dmg); break; default: sprintf(dmm, "%f", dmg); break; } } else sprintf(dmm, "%f", dmg); if(EVENT_SENDER && EVENT_SENDER->summoner == 0) { EVENT_SENDER = entities.player(); sprintf(dmm, "%f summoned", dmg); } if(SendIOScriptEvent(io, SM_HIT, dmm) != ACCEPT) return damagesdone; } } damagesdone = std::min(dmg, io->_npcdata->lifePool.current); io->_npcdata->lifePool.current -= dmg; float fHitFlash = 0; if(io->_npcdata->lifePool.current <= 0) { fHitFlash = 0; } else { fHitFlash = io->_npcdata->lifePool.current / io->_npcdata->lifePool.max; } hitStrengthGaugeRequestFlash(fHitFlash); if(io->_npcdata->lifePool.current <= 0.f) { io->_npcdata->lifePool.current = 0.f; if(source != PlayerEntityHandle || (source == PlayerEntityHandle && player.equiped[EQUIP_SLOT_WEAPON] > 0)) { if((dmg >= io->_npcdata->lifePool.max * ( 1.0f / 2 )) && pos) ARX_NPC_TryToCutSomething(io, pos); } if(ValidIONum(source)) { long xp = io->_npcdata->xpvalue; ARX_DAMAGES_ForceDeath(io, entities[source]); if(source == 0 || entities[source]->summoner == 0) ARX_PLAYER_Modify_XP(xp); } else ARX_DAMAGES_ForceDeath(io, NULL); } } return damagesdone; }
// source = -1 no source but valid pos // source = 0 player // source > 0 IO static void ARX_DAMAGES_UpdateDamage(DamageHandle j, float tim) { DAMAGE_INFO & damage = damages[j]; if(!damage.exist) { return; } if(damage.params.flags & DAMAGE_FLAG_FOLLOW_SOURCE) { if(damage.params.source == PlayerEntityHandle) { damage.params.pos = player.pos; } else if (ValidIONum(damage.params.source)) { damage.params.pos = entities[damage.params.source]->pos; } } float dmg; if(damage.params.flags & DAMAGE_NOT_FRAME_DEPENDANT) { dmg = damage.params.damages; } else if(damage.params.duration == -1) { dmg = damage.params.damages; } else { float FD = (float)framedelay; if(tim > damage.start_time + damage.params.duration) { FD -= damage.start_time + damage.params.duration - tim; } dmg = damage.params.damages * FD * ( 1.0f / 1000 ); } bool validsource = ValidIONum(damage.params.source); float divradius = 1.f / damage.params.radius; // checking for IO damages for(size_t i = 0; i < entities.size(); i++) { const EntityHandle handle = EntityHandle(i); Entity * io = entities[handle]; if(io && (io->gameFlags & GFLAG_ISINTREATZONE) && (io->show == SHOW_FLAG_IN_SCENE) && (damage.params.source != long(i) || (damage.params.source == long(i) && !(damage.params.flags & DAMAGE_FLAG_DONT_HURT_SOURCE))) ){ if(io->ioflags & IO_NPC) { if( i != 0 && damage.params.source != PlayerEntityHandle && validsource && HaveCommonGroup(io, entities[damage.params.source]) ) { continue; } Sphere sphere; sphere.origin = damage.params.pos; sphere.radius = damage.params.radius - 10.f; if(CheckIOInSphere(sphere, EntityHandle(i), true)) { Vec3f sub = io->pos + Vec3f(0.f, -60.f, 0.f); float dist = fdist(damage.params.pos, sub); if(damage.params.type & DAMAGE_TYPE_FIELD) { if(float(arxtime) > io->collide_door_time + 500) { EVENT_SENDER = NULL; io->collide_door_time = (unsigned long)(arxtime); char param[64]; param[0] = 0; if(damage.params.type & DAMAGE_TYPE_FIRE) strcpy(param, "fire"); if(damage.params.type & DAMAGE_TYPE_COLD) strcpy(param, "cold"); SendIOScriptEvent(io, SM_COLLIDE_FIELD, param); } } switch(damage.params.area) { case DAMAGE_AREA: { float ratio = (damage.params.radius - dist) * divradius; ratio = glm::clamp(ratio, 0.f, 1.f); dmg = dmg * ratio + 1.f; } break; case DAMAGE_AREAHALF: { float ratio = (damage.params.radius - (dist * ( 1.0f / 2 ))) * divradius; ratio = glm::clamp(ratio, 0.f, 1.f); dmg = dmg * ratio + 1.f; } break; case DAMAGE_FULL: break; } if(dmg <= 0.f) continue; if( (damage.params.flags & DAMAGE_FLAG_ADD_VISUAL_FX) && (entities[handle]->ioflags & IO_NPC) && (entities[handle]->_npcdata->lifePool.current > 0.f) ) { ARX_DAMAGES_AddVisual(&damage, &sub, dmg, entities[handle]); } if(damage.params.type & DAMAGE_TYPE_DRAIN_MANA) { float manadrained; if(i == 0) { manadrained = std::min(dmg, player.manaPool.current); player.manaPool.current -= manadrained; } else { manadrained = dmg; if(io && io->_npcdata) { manadrained = std::min(dmg, io->_npcdata->manaPool.current); io->_npcdata->manaPool.current -= manadrained; } } if (damage.params.source == PlayerEntityHandle) { player.manaPool.current = std::min(player.manaPool.current + manadrained, player.Full_maxmana); } else { if(ValidIONum(damage.params.source) && (entities[damage.params.source]->_npcdata)) { entities[damage.params.source]->_npcdata->manaPool.current = std::min(entities[damage.params.source]->_npcdata->manaPool.current + manadrained, entities[damage.params.source]->_npcdata->manaPool.max); } } } else { float damagesdone; // TODO copy-paste if(i == 0) { if(damage.params.type & DAMAGE_TYPE_POISON) { if(rnd() * 100.f > player.m_misc.resistPoison) { // Failed Saving Throw damagesdone = dmg; player.poison += damagesdone; } else { damagesdone = 0; } } else { if( (damage.params.type & DAMAGE_TYPE_MAGICAL) && !(damage.params.type & DAMAGE_TYPE_FIRE) && !(damage.params.type & DAMAGE_TYPE_COLD) ) { dmg -= player.m_miscFull.resistMagic * ( 1.0f / 100 ) * dmg; dmg = std::max(0.0f, dmg); } if(damage.params.type & DAMAGE_TYPE_FIRE) { dmg = ARX_SPELLS_ApplyFireProtection(entities.player(), dmg); ARX_DAMAGES_IgnitIO(entities.player(), dmg); } if(damage.params.type & DAMAGE_TYPE_COLD) { dmg = ARX_SPELLS_ApplyColdProtection(entities.player(), dmg); } damagesdone = ARX_DAMAGES_DamagePlayer(dmg, damage.params.type, damage.params.source); } } else { if( (entities[handle]->ioflags & IO_NPC) && (damage.params.type & DAMAGE_TYPE_POISON) ) { if(rnd() * 100.f > entities[handle]->_npcdata->resist_poison) { // Failed Saving Throw damagesdone = dmg; entities[handle]->_npcdata->poisonned += damagesdone; } else { damagesdone = 0; } } else { if(damage.params.type & DAMAGE_TYPE_FIRE) { dmg = ARX_SPELLS_ApplyFireProtection(entities[handle], dmg); ARX_DAMAGES_IgnitIO(entities[handle], dmg); } if( (damage.params.type & DAMAGE_TYPE_MAGICAL) && !(damage.params.type & DAMAGE_TYPE_FIRE) && !(damage.params.type & DAMAGE_TYPE_COLD) ) { dmg -= entities[handle]->_npcdata->resist_magic * ( 1.0f / 100 ) * dmg; dmg = std::max(0.0f, dmg); } if(damage.params.type & DAMAGE_TYPE_COLD) { dmg = ARX_SPELLS_ApplyColdProtection(entities[handle], dmg); } damagesdone = ARX_DAMAGES_DamageNPC(entities[handle], dmg, damage.params.source, true, &damage.params.pos); } if(damagesdone > 0 && (damage.params.flags & DAMAGE_SPAWN_BLOOD)) { ARX_PARTICLES_Spawn_Blood(&damage.params.pos, damagesdone, damage.params.source); } } if(damage.params.type & DAMAGE_TYPE_DRAIN_LIFE) { if(ValidIONum(damage.params.source)) ARX_DAMAGES_HealInter(entities[damage.params.source], damagesdone); } } } } else if((io->ioflags & IO_FIX) && !(damage.params.type & DAMAGE_TYPE_NO_FIX)) { Sphere sphere; sphere.origin = damage.params.pos; sphere.radius = damage.params.radius + 15.f; if(CheckIOInSphere(sphere, EntityHandle(i))) { ARX_DAMAGES_DamageFIX(io, dmg, damage.params.source, true); } } } } if(damage.params.duration == -1) damage.exist = false; else if(tim > damage.start_time + damage.params.duration) damage.exist = false; }
void TreatBackgroundDynlights() { ARX_PROFILE_FUNC(); for(size_t i = 0; i < MAX_LIGHTS; i++) { EERIE_LIGHT *light = GLight[i]; if(light && (light->extras & EXTRAS_SEMIDYNAMIC)) { float fMaxdist = player.m_telekinesis ? 850 : 300; if(!fartherThan(light->pos, ACTIVECAM->orgTrans.pos, fMaxdist)) { ComputeLight2DPos(light); } else { light->m_screenRect.max.x = -1; light->m_screenRect.min.x = 1; } if(!light->m_ignitionStatus) { // just extinguished if(lightHandleIsValid(light->m_ignitionLightHandle)) { lightHandleGet(light->m_ignitionLightHandle)->exist = 0; light->m_ignitionLightHandle = LightHandle(); for(size_t l = 0; l < entities.size(); l++) { const EntityHandle handle = EntityHandle(l); Entity * e = entities[handle]; if(e && (e->ioflags & IO_MARKER)) { Vec3f _pos2 = GetItemWorldPosition(e); if(!fartherThan(light->pos, _pos2, 300.f)) { SendIOScriptEvent(e, SM_CUSTOM, "douse"); } } } } } else { // just light up if(!lightHandleIsValid(light->m_ignitionLightHandle)) { for(size_t l = 0; l < entities.size(); l++) { const EntityHandle handle = EntityHandle(l); Entity * e = entities[handle]; if(e && (e->ioflags & IO_MARKER)) { Vec3f _pos2 = GetItemWorldPosition(e); if(!fartherThan(light->pos, _pos2, 300.f)) { SendIOScriptEvent(e, SM_CUSTOM, "fire"); } } } light->m_ignitionLightHandle = GetFreeDynLight(); } if(lightHandleIsValid(light->m_ignitionLightHandle)) { EERIE_LIGHT *dynamicLight = lightHandleGet(light->m_ignitionLightHandle); dynamicLight->pos = light->pos; dynamicLight->fallstart = light->fallstart; dynamicLight->fallend = light->fallend; dynamicLight->m_isIgnitionLight = true; dynamicLight->intensity = light->intensity; dynamicLight->ex_flaresize = light->ex_flaresize; dynamicLight->extras = light->extras; dynamicLight->duration = std::numeric_limits<long>::max(); dynamicLight->rgb = light->rgb - light->rgb * light->ex_flicker * randomColor3f() * 0.5f; dynamicLight->rgb = componentwise_max(dynamicLight->rgb, Color3f::black); RecalcLight(dynamicLight); } } } } for(size_t i = 0; i < MAX_DYNLIGHTS; i++) { EERIE_LIGHT * el = &DynLight[i]; if(el->exist && el->duration) { float tim = (float)float(arxtime) - (float)el->time_creation; float duration = (float)el->duration; if(tim >= duration) { float sub = framedelay * 0.001f; el->rgb.r -= sub; el->rgb.g -= sub; el->rgb.b -= sub; if(el->rgb.r < 0) el->rgb.r = 0.f; if(el->rgb.g < 0) el->rgb.g = 0.f; if(el->rgb.b < 0) el->rgb.b = 0.f; if(el->rgb.r + el->rgb.g + el->rgb.b == 0) { el->exist = 0; el->duration = 0; } } } } }