void NegateMagicSpell::LaunchAntiMagicField() { if(!ValidIONum(m_target)) { return; } for(size_t i = 0; i < MAX_SPELLS; i++) { SpellBase * spell = spells[SpellHandle(i)]; if(!spell || this == spell || m_level < spell->m_level) { continue; } Vec3f pos = spell->getPosition(); if(closerThan(pos, entities[m_target]->pos, 600.f)) { if(spell->m_type != SPELL_CREATE_FIELD) { spells.endSpell(spell); } else if(m_target == EntityHandle_Player && spell->m_caster == EntityHandle_Player) { spells.endSpell(spell); } } } }
void ARX_THROWN_OBJECT_Throw(EntityHandle source, const Vec3f & position, const Vec3f & vect, const glm::quat & quat, float velocity, float damages, float poison) { arx_assert(arrowobj); long num = ARX_THROWN_OBJECT_GetFree(); if(num < 0) return; Projectile & projectile = g_projectiles[num]; projectile.damages = damages; projectile.position = position; projectile.initial_position = position; projectile.vector = vect; projectile.quat = quat; projectile.source = source; projectile.obj = arrowobj; projectile.velocity = velocity; projectile.poisonous = poison; projectile.m_trail = new ArrowTrail(); projectile.m_trail->SetNextPosition(projectile.position); projectile.m_trail->Update(g_framedelay); projectile.creation_time = arxtime.now_ul(); projectile.flags |= ATO_EXIST | ATO_MOVING; if(source == PlayerEntityHandle && ValidIONum(player.equiped[EQUIP_SLOT_WEAPON]) ) { Entity * tio = entities[player.equiped[EQUIP_SLOT_WEAPON]]; if(tio->ioflags & IO_FIERY) projectile.flags |= ATO_FIERY; } }
void ARX_THROWN_OBJECT_Throw(EntityHandle source, const Vec3f & position, const Vec3f & vect, const glm::quat & quat, float velocity, float damages, float poison) { arx_assert(arrowobj); long num = ARX_THROWN_OBJECT_GetFree(); if(num < 0) return; ARX_THROWN_OBJECT *thrownObj = &Thrown[num]; thrownObj->damages = damages; thrownObj->position = position; thrownObj->initial_position = position; thrownObj->vector = vect; thrownObj->quat = quat; thrownObj->source = source; thrownObj->obj = arrowobj; thrownObj->velocity = velocity; thrownObj->poisonous = poison; thrownObj->pRuban = new ArrowTrail(); thrownObj->pRuban->SetNextPosition(thrownObj->position); thrownObj->pRuban->Update(framedelay); thrownObj->creation_time = (unsigned long)(arxtime); thrownObj->flags |= ATO_EXIST | ATO_MOVING; if(source == 0 && ValidIONum(player.equiped[EQUIP_SLOT_WEAPON]) ) { Entity * tio = entities[player.equiped[EQUIP_SLOT_WEAPON]]; if(tio->ioflags & IO_FIERY) thrownObj->flags |= ATO_FIERY; } }
float getEquipmentBaseModifier(EquipmentModifierType modifier, bool getRelative) { float sum = 0; for(size_t i = 0; i < MAX_EQUIPED; i++) { if(ValidIONum(player.equiped[i])) { Entity * toequip = entities[player.equiped[i]]; if(toequip && (toequip->ioflags & IO_ITEM) && toequip->_itemdata->equipitem) { IO_EQUIPITEM_ELEMENT * elem = &toequip->_itemdata->equipitem->elements[modifier]; bool isRelative = elem->flags.has(IO_ELEMENT_FLAG_PERCENT); if(isRelative == getRelative) { sum += elem->value; } } } } if(getRelative) { // Convert from percent to ratio sum *= 0.01f; } return sum; }
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 IceFieldSpell::Launch() { spells.endByCaster(m_caster, SPELL_ICE_FIELD); ARX_SOUND_PlaySFX(SND_SPELL_ICE_FIELD); m_duration = (m_launchDuration > -1) ? m_launchDuration : 100000; m_hasDuration = true; m_fManaCostPerSecond = 2.8f; m_light = LightHandle::Invalid; Vec3f target; float beta = 0.f; bool displace = false; if(m_caster == PlayerEntityHandle) { target = player.basePosition(); beta = player.angle.getPitch(); displace = true; } else { if(ValidIONum(m_caster)) { Entity * io = entities[m_caster]; target = io->pos; beta = io->angle.getPitch(); displace = (io->ioflags & IO_NPC) == IO_NPC; } else { ARX_DEAD_CODE(); } } if(displace) { target += angleToVectorXZ(beta) * 250.f; } m_pos = target; DamageParameters damage; damage.radius = 150.f; damage.damages = 10.f; damage.area = DAMAGE_FULL; damage.duration = 100000000; damage.source = m_caster; damage.flags = 0; damage.type = DAMAGE_TYPE_MAGICAL | DAMAGE_TYPE_COLD | DAMAGE_TYPE_FIELD; damage.pos = target; m_damage = DamageCreate(damage); tex_p1 = TextureContainer::Load("graph/obj3d/textures/(fx)_tsu_blueting"); tex_p2 = TextureContainer::Load("graph/obj3d/textures/(fx)_tsu_bluepouf"); for(int i = 0; i < iMax; i++) { float t = rnd(); if (t < 0.5f) tType[i] = 0; else tType[i] = 1; tSize[i] = Vec3f_ZERO; tSizeMax[i] = Vec3f(rnd(), rnd(), rnd()) + Vec3f(0.f, 0.2f, 0.f); Vec3f minPos; if(tType[i] == 0) { minPos = Vec3f(1.2f, 1, 1.2f); } else { minPos = Vec3f(0.4f, 0.3f, 0.4f); } tSizeMax[i] = glm::max(tSizeMax[i], minPos); if(tType[i] == 0) { tPos[i].x = m_pos.x + frand2() * 80; tPos[i].y = m_pos.y; tPos[i].z = m_pos.z + frand2() * 80; } else { tPos[i].x = m_pos.x + frand2() * 120; tPos[i].y = m_pos.y; tPos[i].z = m_pos.z + frand2() * 120; } } m_snd_loop = ARX_SOUND_PlaySFX(SND_SPELL_ICE_FIELD_LOOP, &target, 1.f, ARX_SOUND_PLAY_LOOPED); }
void levelInit() { arx_assert(entities.player()); LogDebug("Initializing level ..."); g_requestLevelInit = true; ARX_PARTICLES_FirstInit(); RenderBatcher::getInstance().reset(); progressBarAdvance(2.f); LoadLevelScreen(); if(!pParticleManager) pParticleManager = new ParticleManager(); if(GMOD_RESET) ARX_GLOBALMODS_Reset(); GMOD_RESET = true; STARTDRAG = Vec2s_ZERO; DANAEMouse = Vec2s_ZERO; if(LOAD_N_ERASE) arxtime.init(); ARX_BOOMS_ClearAllPolyBooms(); ARX_DAMAGES_Reset(); ARX_MISSILES_ClearAll(); spells.clearAll(); ARX_SPELLS_ClearAllSymbolDraw(); ARX_PARTICLES_ClearAll(); if(LOAD_N_ERASE) { CleanScriptLoadedIO(); RestoreInitialIOStatus(); DRAGINTER=NULL; } ARX_SPELLS_ResetRecognition(); eyeball.exist=0; for(size_t i = 0; i < MAX_DYNLIGHTS; i++) { lightHandleGet((LightHandle)i)->exist = 0; } arxtime.update_last_frame_time(); if(LOAD_N_ERASE) { CleanInventory(); ARX_SCRIPT_Timer_ClearAll(); UnlinkAllLinkedObjects(); ARX_SCRIPT_ResetAll(false); } SecondaryInventory=NULL; TSecondaryInventory=NULL; ARX_FOGS_Render(); if(LOAD_N_ERASE) { arxtime.init(); if(!DONT_ERASE_PLAYER) ARX_PLAYER_InitPlayer(); g_hudRoot.playerInterfaceFader.resetSlid(); player.lifePool.current = player.lifePool.max; player.manaPool.current = player.manaPool.max; if(!DONT_ERASE_PLAYER) { ARX_PLAYER_MakeFreshHero(); } } InitSnapShot(fs::paths.user / "snapshot"); if(FASTmse) { FASTmse = 0; if(LOADEDD) { Vec3f trans = Mscenepos; player.pos = loddpos + trans; } else { player.pos.y += player.baseHeight(); } progressBarAdvance(4.f); LoadLevelScreen(); } #if BUILD_EDIT_LOADSAVE else if(mse) { Mscenepos.x=-mse->cub.xmin-(mse->cub.xmax-mse->cub.xmin)*.5f+((float)ACTIVEBKG->Xsize*(float)ACTIVEBKG->Xdiv)*.5f; Mscenepos.z=-mse->cub.zmin-(mse->cub.zmax-mse->cub.zmin)*.5f+((float)ACTIVEBKG->Zsize*(float)ACTIVEBKG->Zdiv)*.5f; float t1=(float)(long)(mse->point0.x/BKG_SIZX); float t2=(float)(long)(mse->point0.z/BKG_SIZZ); t1=mse->point0.x-t1*BKG_SIZX; t2=mse->point0.z-t2*BKG_SIZZ; Mscenepos.x=(float)((long)(Mscenepos.x/BKG_SIZX))*BKG_SIZX+(float)BKG_SIZX*.5f; Mscenepos.z=(float)((long)(Mscenepos.z/BKG_SIZZ))*BKG_SIZZ+(float)BKG_SIZZ*.5f; mse->pos.x=Mscenepos.x=Mscenepos.x+BKG_SIZX-t1; mse->pos.z=Mscenepos.z=Mscenepos.z+BKG_SIZZ-t2; Mscenepos.y=mse->pos.y=-mse->cub.ymin-100.f-mse->point0.y; if (PLAYER_POSITION_RESET) { player.pos.x = mse->pos.x+mse->point0.x; player.pos.z = mse->pos.z+mse->point0.z; player.pos.y = mse->pos.y+mse->point0.y; } EERIERemovePrecalcLights(); progressBarAdvance(); LoadLevelScreen(); SceneAddMultiScnToBackground(mse); progressBarAdvance(2.f); LoadLevelScreen(); Vec3f trans = mse->pos; ReleaseMultiScene(mse); mse=NULL; if(PLAYER_POSITION_RESET) { if(LOADEDD) { player.pos = loddpos + trans; } else { player.pos.y += player.baseHeight(); } } PLAYER_POSITION_RESET = true; progressBarAdvance(); LoadLevelScreen(); } #endif // BUILD_EDIT_LOADSAVE else { progressBarAdvance(4.f); LoadLevelScreen(); } if(player.torch) { ARX_SOUND_PlaySFX(SND_TORCH_LOOP, NULL, 1.0F, ARX_SOUND_PLAY_LOOPED); } MagicFlareSetCamera(&subj); lastteleport = player.basePosition(); subj.orgTrans.pos = g_moveto = player.pos; subj.angle = player.angle; RestoreLastLoadedLightning(*ACTIVEBKG); progressBarAdvance(); LoadLevelScreen(); if(LOAD_N_ERASE) SetEditMode(0); progressBarAdvance(); LoadLevelScreen(); LOAD_N_ERASE = true; DONT_ERASE_PLAYER=0; progressBarAdvance(); LoadLevelScreen(); g_requestLevelInit = false; PrepareIOTreatZone(1); CURRENTLEVEL=GetLevelNumByName(LastLoadedScene.string()); if(TIME_INIT) arxtime.init(); arxtime.update_last_frame_time(); progressBarAdvance(); LoadLevelScreen(); if(DONT_WANT_PLAYER_INZONE) { player.inzone = NULL; DONT_WANT_PLAYER_INZONE = 0; } progressBarAdvance(); LoadLevelScreen(); player.desiredangle.setYaw(0.f); player.angle.setYaw(0.f); ARX_PLAYER_RectifyPosition(); entities.player()->_npcdata->vvpos = -99999; SendGameReadyMsg(); PLAYER_MOUSELOOK_ON = false; player.Interface &= ~INTER_NOTE; if(!TIME_INIT) { arxtime.force_time_restore(FORCE_TIME_RESTORE); arxtime.force_frame_time_restore(FORCE_TIME_RESTORE); } else { arxtime.resume(); } EntityHandle t = entities.getById("seat_stool1_0012"); if(ValidIONum(t)) { entities[t]->ioflags |= IO_FORCEDRAW; } if(WILL_RESTORE_PLAYER_POSITION_FLAG) { Entity * io = entities.player(); player.pos = WILL_RESTORE_PLAYER_POSITION; io->pos = player.basePosition(); for(size_t i = 0; i < io->obj->vertexlist.size(); i++) { io->obj->vertexlist3[i].v = io->obj->vertexlist[i].v + io->pos; } WILL_RESTORE_PLAYER_POSITION_FLAG = 0; } ARX_NPC_RestoreCuts(); ResetVVPos(entities.player()); progressBarAdvance(); LoadLevelScreen(); LoadLevelScreen(-2); if ( (!CheckInPoly(player.pos)) && (LastValidPlayerPos.x!=0.f) && (LastValidPlayerPos.y!=0.f) && (LastValidPlayerPos.z!=0.f)) { player.pos = LastValidPlayerPos; } LastValidPlayerPos = player.pos; }
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 FireFieldSpell::Launch() { spells.endByCaster(m_caster, SPELL_FIRE_FIELD); ARX_SOUND_PlaySFX(SND_SPELL_FIRE_FIELD_START); m_duration = (m_launchDuration > -1) ? m_launchDuration : 100000; m_hasDuration = true; m_fManaCostPerSecond = 2.8f; m_light = LightHandle::Invalid; Vec3f target; float beta = 0.f; bool displace = false; if(m_caster == PlayerEntityHandle) { target = player.basePosition(); beta = player.angle.getPitch(); displace = true; } else { if(ValidIONum(m_caster)) { Entity * io = entities[m_caster]; target = io->pos; beta = io->angle.getPitch(); displace = (io->ioflags & IO_NPC) == IO_NPC; } else { ARX_DEAD_CODE(); } } if(displace) { target += angleToVectorXZ(beta) * 250.f; } m_pos = target + Vec3f(0, -10, 0); DamageParameters damage; damage.radius = 150.f; damage.damages = 10.f; damage.area = DAMAGE_FULL; damage.duration = 100000000; damage.source = m_caster; damage.flags = 0; damage.type = DAMAGE_TYPE_MAGICAL | DAMAGE_TYPE_FIRE | DAMAGE_TYPE_FIELD; damage.pos = target; m_damage = DamageCreate(damage); m_snd_loop = ARX_SOUND_PlaySFX(SND_SPELL_FIRE_FIELD_LOOP, &target, 1.f, ARX_SOUND_PLAY_LOOPED); { ParticleParams cp = ParticleParams(); cp.m_nbMax = 100; cp.m_life = 2000; cp.m_lifeRandom = 1000; cp.m_pos = Vec3f(80, 10, 80); cp.m_direction = Vec3f(0.f, 1.f, 0.f); cp.m_angle = 0; cp.m_speed = 0; cp.m_speedRandom = 0; cp.m_gravity = Vec3f_ZERO; cp.m_flash = 0; cp.m_rotation = 0; cp.m_rotationRandomDirection = false; cp.m_rotationRandomStart = false; cp.m_startSegment.m_size = 10; cp.m_startSegment.m_sizeRandom = 3; cp.m_startSegment.m_color = Color(25, 25, 25, 50).to<float>(); cp.m_startSegment.m_colorRandom = Color(51, 51, 51, 101).to<float>(); cp.m_endSegment.m_size = 10; cp.m_endSegment.m_sizeRandom = 3; cp.m_endSegment.m_color = Color(25, 25, 25, 50).to<float>(); cp.m_endSegment.m_colorRandom = Color(0, 0, 0, 100).to<float>(); cp.m_texture.m_texLoop = true; cp.m_blendMode = RenderMaterial::AlphaAdditive; cp.m_freq = 150.0f; cp.m_texture.set("graph/particles/firebase", 4, 100); cp.m_spawnFlags = 0; pPSStream.SetParams(cp); } pPSStream.SetPos(m_pos); pPSStream.Update(0); //------------------------------------------------------------------------- { ParticleParams cp = ParticleParams(); cp.m_nbMax = 50; cp.m_life = 1000; cp.m_lifeRandom = 500; cp.m_pos = Vec3f(100, 10, 100); cp.m_direction = Vec3f(0.f, -1.f, 0.f); cp.m_angle = glm::radians(10.f); cp.m_speed = 0; cp.m_speedRandom = 0; cp.m_gravity = Vec3f_ZERO; cp.m_flash = 0; cp.m_rotation = 0; cp.m_rotationRandomDirection = false; cp.m_rotationRandomStart = false; cp.m_startSegment.m_size = 10; cp.m_startSegment.m_sizeRandom = 10; cp.m_startSegment.m_color = Color(40, 40, 40, 50).to<float>(); cp.m_startSegment.m_colorRandom = Color(51, 51, 51, 100).to<float>(); cp.m_endSegment.m_size = 10; cp.m_endSegment.m_sizeRandom = 10; cp.m_endSegment.m_color = Color(0, 0, 0, 50).to<float>(); cp.m_endSegment.m_colorRandom = Color(0, 0, 0, 100).to<float>(); cp.m_texture.m_texLoop = false; cp.m_blendMode = RenderMaterial::Additive; cp.m_freq = 150.0f; cp.m_texture.set("graph/particles/fire", 0, 500); cp.m_spawnFlags = 0; pPSStream1.SetParams(cp); } pPSStream1.SetPos(m_pos + Vec3f(0, 10, 0)); pPSStream1.Update(0); }
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; }
//************************************************************************************* // 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; }
//--------------------------------------------------------------------- void CHeal::Update(unsigned long aulTime) { ulCurrentTime += aulTime; if (ulCurrentTime >= ulDuration) { return; } if (spells[spellinstance].caster == 0) { eSrc.x = player.pos.x; eSrc.y = player.pos.y; eSrc.z = player.pos.z; } else { if (ValidIONum(spells[spellinstance].target)) { eSrc.x = inter.iobj[spells[spellinstance].target]->pos.x; eSrc.y = inter.iobj[spells[spellinstance].target]->pos.y; eSrc.z = inter.iobj[spells[spellinstance].target]->pos.z; } } if (pPS->lLightId == -1) pPS->lLightId = GetFreeDynLight(); if (pPS->lLightId != -1) { long id = pPS->lLightId; DynLight[id].exist = 1; DynLight[id].intensity = 2.3f; DynLight[id].fallstart = 200.f; DynLight[id].fallend = 350.f; DynLight[id].rgb.r = 0.4f; DynLight[id].rgb.g = 0.4f; DynLight[id].rgb.b = 1.0f; DynLight[id].pos.x = eSrc.x; DynLight[id].pos.y = eSrc.y - 50.f; DynLight[id].pos.z = eSrc.z; DynLight[id].duration = 200; DynLight[id].extras = 0; } unsigned long ulCalc = ulDuration - ulCurrentTime ; ARX_CHECK_LONG(ulCalc); long ff = ARX_CLEAN_WARN_CAST_LONG(ulCalc); if (ff < 1500) { pPS->uMaxParticles = 0; pPS->ulParticleSpawn = PARTICLE_CIRCULAR; pPS->p3ParticleGravity.x = 0; pPS->p3ParticleGravity.y = 0; pPS->p3ParticleGravity.z = 0; list<CParticle *>::iterator i; for (i = pPS->listParticle.begin(); i != pPS->listParticle.end(); ++i) { CParticle * pP = *i; if (pP->isAlive()) { pP->fColorEnd[3] = 0; if (pP->ulTime + ff < pP->ulTTL) { pP->ulTime = pP->ulTTL - ff; } } } } pPS->SetPos(eSrc); pPS->Update(aulTime); }
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 ShowInfoText() { DebugBox frameInfo = DebugBox(Vec2i(10, 10), "FrameInfo"); frameInfo.add("Prims", EERIEDrawnPolys); frameInfo.add("Particles", getParticleCount()); frameInfo.add("Polybooms", long(polyboom.size())); frameInfo.add("TIME", static_cast<long>(arxtime.now_ul() / 1000)); frameInfo.print(); DebugBox playerBox = DebugBox(Vec2i(10, frameInfo.size().y + 5), "Player"); playerBox.add("Position", player.pos); playerBox.add("AnchorPos", player.pos - Mscenepos); playerBox.add("Rotation", player.angle); playerBox.add("Velocity", player.physics.velocity); EERIEPOLY * ep = CheckInPoly(player.pos); float truePolyY = -666.66f; if(ep) { float tempY = 0.f; if(GetTruePolyY(ep, player.pos, &tempY)) { truePolyY = tempY; } } ep = CheckInPoly(player.pos + Vec3f(0.f, -10.f, 0.f)); float slope = 0.f; if(ep) slope = ep->norm.y; long zap = IsAnyPolyThere(player.pos.x,player.pos.z); playerBox.add("Ground Slope", slope); playerBox.add("Ground truePolyY", truePolyY); playerBox.add("Ground POLY", zap); playerBox.add("Color", CURRENT_PLAYER_COLOR); playerBox.add("Stealth", GetPlayerStealth()); playerBox.add("Jump", player.jumplastposition); playerBox.add("OFFGRND", (!player.onfirmground ? "OFFGRND" : "")); playerBox.add("Life", player.lifePool); playerBox.add("Mana", player.manaPool); playerBox.add("Poisoned", player.poison); playerBox.add("Hunger", player.hunger); playerBox.add("Magic", static_cast<long>(player.doingmagic)); playerBox.print(); DebugBox miscBox = DebugBox(Vec2i(10, playerBox.size().y + 5), "Misc"); miscBox.add("Arx version", arx_version); miscBox.add("Level", LastLoadedScene.string().c_str()); miscBox.add("Spell failed seq", LAST_FAILED_SEQUENCE.c_str()); miscBox.add("Camera focal", ACTIVECAM->focal); miscBox.add("Cinema", cinematicBorder.CINEMA_DECAL); miscBox.add("Mouse", Vec2i(DANAEMouse)); miscBox.add("Pathfind queue", EERIE_PATHFINDER_Get_Queued_Number()); miscBox.add("Pathfind status", (PATHFINDER_WORKING ? "Working" : "Idled")); miscBox.print(); { struct ScriptDebugReport { std::string entityName; long events; long sends; ScriptDebugReport() : entityName("") , events(0) , sends(0) {} }; ScriptDebugReport maxEvents; Entity * io = ARX_SCRIPT_Get_IO_Max_Events(); if(io) { maxEvents.entityName = io->idString(); maxEvents.events = io->stat_count; } ScriptDebugReport maxSender; io = ARX_SCRIPT_Get_IO_Max_Events_Sent(); if(io) { maxSender.entityName = io->idString(); maxSender.sends = io->stat_sent; } DebugBox scriptBox = DebugBox(Vec2i(10, miscBox.size().y + 5), "Script"); scriptBox.add("Events", ScriptEvent::totalCount); scriptBox.add("Timers", ARX_SCRIPT_CountTimers()); scriptBox.add("Max events", maxEvents.entityName); scriptBox.add("Max events#", maxEvents.events); scriptBox.add("Max sender", maxSender.entityName); scriptBox.add("Max sender#", maxSender.sends); scriptBox.print(); } if(ValidIONum(LastSelectedIONum)) { Entity * io = entities[LastSelectedIONum]; if(io) { DebugBox entityBox = DebugBox(Vec2i(500, 10), "Entity " + io->idString()); entityBox.add("Pos", io->pos); entityBox.add("Angle", io->angle); entityBox.add("Room", static_cast<long>(io->room)); entityBox.add("Move", io->move); entityBox.add("Flags", flagNames(EntityFlagNames, io->ioflags)); entityBox.add("Show", entityVisilibityToString(io->show)); entityBox.print(); if(io->ioflags & IO_NPC) { IO_NPCDATA * npcData = io->_npcdata; DebugBox npcBox = DebugBox(Vec2i(500, entityBox.size().y + 5), "NPC"); npcBox.add("Life", npcData->lifePool); npcBox.add("Mana", npcData->manaPool); npcBox.add("Poisoned", npcData->poisonned); npcBox.add("ArmorClass", ARX_INTERACTIVE_GetArmorClass(io)); npcBox.add("Absorb", npcData->absorb); npcBox.add("Moveproblem", npcData->moveproblem); npcBox.add("Pathfind listpos", static_cast<long>(npcData->pathfind.listpos)); npcBox.add("Pathfind listnb", npcData->pathfind.listnb); npcBox.add("Pathfind targ", npcData->pathfind.truetarget.handleData()); npcBox.add("Behavior", flagNames(BehaviourFlagNames, npcData->behavior)); // TODO should those really be flags ? PathfindFlags pflag = io->_npcdata->pathfind.flags; std::string pflags; if(pflag & PATHFIND_ALWAYS) pflags += "ALWAYS "; if(pflag & PATHFIND_ONCE) pflags += "ONCE "; if(pflag & PATHFIND_NO_UPDATE) pflags += "NO_UPDATE "; npcBox.add("Pathfind flgs", pflags); npcBox.print(); } if(io->ioflags & (IO_FIX | IO_ITEM)) { DebugBox itemBox = DebugBox(Vec2i(500, entityBox.size().y + 5), "Item"); itemBox.add("Durability", io->durability); itemBox.add("Durability max", io->max_durability); itemBox.add("Poisonous", static_cast<long>(io->poisonous)); itemBox.add("Poisonous count", static_cast<long>(io->poisonous_count)); itemBox.print(); } } } ARX_SCRIPT_Init_Event_Stats(); }
//TODO Move somewhere else void Cedric_ApplyLightingFirstPartRefactor(Entity *io) { if(!io) return; io->special_color = Color3f::white; float poisonpercent = 0.f; float trappercent = 0.f; float secretpercent = 0.f; if((io->ioflags & IO_NPC) && io->_npcdata->poisonned > 0.f) { poisonpercent = io->_npcdata->poisonned * ( 1.0f / 20 ); if(poisonpercent > 1.f) poisonpercent = 1.f; } if((io->ioflags & IO_ITEM) && io->poisonous > 0.f && io->poisonous_count) { poisonpercent = (float)io->poisonous * (1.0f / 20); if(poisonpercent > 1.f) poisonpercent = 1.f; } if((io->ioflags & IO_FIX) && io->_fixdata->trapvalue > -1) { trappercent = player.TRAP_DETECT - (float)io->_fixdata->trapvalue; if(trappercent > 0.f) { trappercent = 0.6f + trappercent * ( 1.0f / 100 ); trappercent = clamp(trappercent, 0.6f, 1.f); } } if((io->ioflags & IO_FIX) && io->secretvalue > -1) { secretpercent = player.TRAP_SECRET - (float)io->secretvalue; if(secretpercent > 0.f) { secretpercent = 0.6f + secretpercent * ( 1.0f / 100 ); secretpercent = clamp(secretpercent, 0.6f, 1.f); } } if(poisonpercent > 0.f) { io->special_color = Color3f::green; } if(trappercent > 0.f) { io->special_color = Color3f(trappercent, 1.f - trappercent, 1.f - trappercent); } if(secretpercent > 0.f) { io->special_color = Color3f(1.f - secretpercent, 1.f - secretpercent, secretpercent); } if(io->ioflags & IO_FREEZESCRIPT) { io->special_color = Color3f::blue; } if(io->sfx_flag & SFX_TYPE_YLSIDE_DEATH) { if(io->show == SHOW_FLAG_TELEPORTING) { float fTime = io->sfx_time + framedelay; io->sfx_time = checked_range_cast<unsigned long>(fTime); if (io->sfx_time >= (unsigned long)(arxtime)) io->sfx_time = (unsigned long)(arxtime); } else { float elapsed = float(arxtime) - io->sfx_time; if(elapsed > 0.f) { if(elapsed < 3000.f) { // 5 seconds to red float ratio = elapsed * (1.0f / 3000); io->special_color = Color3f(1.f, 1.f - ratio, 1.f - ratio); AddRandomSmoke(io, 1); } else if(elapsed < 6000.f) { // 5 seconds to White float ratio = (elapsed - 3000.f) * (1.0f / 3000); io->special_color = Color3f(1.f, ratio, ratio); AddRandomSmoke(io, 2); } else { // SFX finish io->sfx_time = 0; if(io->ioflags & IO_NPC) { MakePlayerAppearsFX(io); AddRandomSmoke(io, 50); Color3f rgb = io->_npcdata->blood_color.to<float>(); EERIE_SPHERE sp; sp.origin = io->pos; sp.radius = 200.f; long count = 6; while(count--) { SpawnGroundSplat(&sp, &rgb, rnd() * 30.f + 30.f, 1); sp.origin.y -= rnd() * 150.f; ARX_PARTICLES_Spawn_Splat(sp.origin, 200.f, io->_npcdata->blood_color); sp.origin.x = io->pos.x + rnd() * 200.f - 100.f; sp.origin.y = io->pos.y + rnd() * 20.f - 10.f; sp.origin.z = io->pos.z + rnd() * 200.f - 100.f; sp.radius = rnd() * 100.f + 100.f; } long nn = GetFreeDynLight(); if(nn >= 0) { DynLight[nn].exist = 1; DynLight[nn].intensity = 0.7f + 2.f * rnd(); DynLight[nn].fallend = 600.f; DynLight[nn].fallstart = 400.f; DynLight[nn].rgb.r = 1.0f; DynLight[nn].rgb.g = 0.8f; DynLight[nn].rgb.b = .0f; DynLight[nn].pos.x = io->pos.x; DynLight[nn].pos.y = io->pos.y - 80.f; DynLight[nn].pos.z = io->pos.z; DynLight[nn].duration = 600; } if(io->sfx_flag & SFX_TYPE_INCINERATE) { io->sfx_flag &= ~SFX_TYPE_INCINERATE; io->sfx_flag &= ~SFX_TYPE_YLSIDE_DEATH; long num = ARX_SPELLS_GetSpellOn(io, SPELL_INCINERATE); if(num < 0) num = ARX_SPELLS_GetSpellOn(io, SPELL_MASS_INCINERATE); if(num >= 0) { spells[num].tolive = 0; float damages = 20 * spells[num].caster_level; damages = ARX_SPELLS_ApplyFireProtection(io, damages); if (ValidIONum(spells[num].caster)) ARX_DAMAGES_DamageNPC(io, damages, spells[num].caster, 1, &entities[spells[num].caster]->pos); else ARX_DAMAGES_DamageNPC(io, damages, spells[num].caster, 1, &io->pos); ARX_SOUND_PlaySFX(SND_SPELL_FIRE_HIT, &io->pos); } } else { io->sfx_flag &= ~SFX_TYPE_YLSIDE_DEATH; ARX_INTERACTIVE_DestroyIOdelayed(io); } } } } } } }
void ARX_THROWN_OBJECT_Manage(unsigned long time_offset) { for(size_t i = 0; i < MAX_THROWN_OBJECTS; i++) { ARX_THROWN_OBJECT *thrownObj = &Thrown[i]; if(!(thrownObj->flags & ATO_EXIST)) continue; { // Is Object Visible & Near ? EERIE_BKG_INFO * bkgData = getFastBackgroundData(thrownObj->position.x, thrownObj->position.z); if(!bkgData || !bkgData->treat) { continue; } // Now render object ! if(!thrownObj->obj) continue; TransformInfo t(thrownObj->position, thrownObj->quat); DrawEERIEInter_ModelTransform(thrownObj->obj, t); if((thrownObj->flags & ATO_FIERY) && (thrownObj->flags & ATO_MOVING) && !(thrownObj->flags & ATO_UNDERWATER)) { LightHandle id = GetFreeDynLight(); if(lightHandleIsValid(id) && 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 = thrownObj->position; light->ex_flaresize = 40.f; light->extras |= EXTRAS_FLARE; light->duration = static_cast<long>(framedelay * 0.5f); } float p = 3.f; while(p > 0.f) { p -= 0.5f; if(thrownObj->obj) { long notok = 10; std::vector<EERIE_FACE>::iterator it; while(notok-- > 0) { it = Random::getIterator(thrownObj->obj->facelist); arx_assert(it != thrownObj->obj->facelist.end()); if(it->facetype & POLY_HIDE) continue; notok = -1; } if(notok < 0) { Vec3f pos = thrownObj->obj->vertexlist3[it->vid[0]].v; createFireParticles(pos, 2, 180); } } } } if(thrownObj->pRuban) { thrownObj->pRuban->SetNextPosition(thrownObj->position); thrownObj->pRuban->Update(time_offset); } Vec3f original_pos; if(thrownObj->flags & ATO_MOVING) { long need_kill = 0; float mod = (float)time_offset * thrownObj->velocity; original_pos = thrownObj->position; thrownObj->position.x += thrownObj->vector.x * mod; float gmod = 1.f - thrownObj->velocity; gmod = glm::clamp(gmod, 0.f, 1.f); thrownObj->position.y += thrownObj->vector.y * mod + (time_offset * gmod); thrownObj->position.z += thrownObj->vector.z * mod; CheckForIgnition(Sphere(original_pos, 10.f), 0, 2); Vec3f wpos = thrownObj->position; wpos.y += 20.f; EERIEPOLY * ep = EEIsUnderWater(wpos); if(thrownObj->flags & ATO_UNDERWATER) { if(!ep) { thrownObj->flags &= ~ATO_UNDERWATER; ARX_SOUND_PlaySFX(SND_PLOUF, &thrownObj->position); } } else if(ep) { thrownObj->flags |= ATO_UNDERWATER; ARX_SOUND_PlaySFX(SND_PLOUF, &thrownObj->position); } // Check for collision MUST be done after DRAWING !!!! long nbact = thrownObj->obj->actionlist.size(); for(long j = 0; j < nbact; j++) { float rad = GetHitValue(thrownObj->obj->actionlist[j].name); if(rad == -1) continue; rad *= .5f; const Vec3f v0 = thrownObj->obj->vertexlist3[thrownObj->obj->actionlist[j].idx].v; Vec3f dest = original_pos + thrownObj->vector * 95.f; Vec3f orgn = original_pos - thrownObj->vector * 25.f; EERIEPOLY * ep = CheckArrowPolyCollision(orgn, dest); if(ep) { ARX_PARTICLES_Spawn_Spark(v0, 14, 0); CheckExp(i); if(ValidIONum(thrownObj->source)) ARX_NPC_SpawnAudibleSound(v0, entities[thrownObj->source]); thrownObj->flags &= ~ATO_MOVING; thrownObj->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(thrownObj->source)) { char weapon_material[64] = "dagger"; ARX_SOUND_PlayCollision(weapon_material, bkg_material, 1.f, 1.f, v0, entities[thrownObj->source]); } thrownObj->position = original_pos; j = 200; } else if(IsPointInField(v0)) { ARX_PARTICLES_Spawn_Spark(v0, 24, 0); CheckExp(i); if (ValidIONum(thrownObj->source)) ARX_NPC_SpawnAudibleSound(v0, entities[thrownObj->source]); thrownObj->flags &= ~ATO_MOVING; thrownObj->velocity = 0.f; if(ValidIONum(thrownObj->source)) { char weapon_material[64] = "dagger"; char bkg_material[64] = "earth"; ARX_SOUND_PlayCollision(weapon_material, bkg_material, 1.f, 1.f, v0, entities[thrownObj->source]); } thrownObj->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 + thrownObj->vector * precision * 4.5f; sphere.radius = rad + 3.f; std::vector<EntityHandle> sphereContent; if(CheckEverythingInSphere(sphere, thrownObj->source, EntityHandle::Invalid, sphereContent)) { for(size_t jj = 0; jj < sphereContent.size(); jj++) { if(ValidIONum(sphereContent[jj]) && sphereContent[jj] != thrownObj->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(thrownObj->source == 0) { float damages = ARX_THROWN_ComputeDamages(i, thrownObj->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, thrownObj->source, false, &pos); if(Random::getf(0.f, 100.f) > target->_npcdata->resist_poison) { target->_npcdata->poisonned += thrownObj->poisonous; } CheckExp(i); } else { ARX_PARTICLES_Spawn_Spark(v0, 14, 0); ARX_NPC_SpawnAudibleSound(v0, entities[thrownObj->source]); } } } else { // not NPC if(target->ioflags & IO_FIX) { if(ValidIONum(thrownObj->source)) ARX_DAMAGES_DamageFIX(target, 0.1f, thrownObj->source, false); } ARX_PARTICLES_Spawn_Spark(v0, 14, 0); if(ValidIONum(thrownObj->source)) ARX_NPC_SpawnAudibleSound(v0, entities[thrownObj->source]); CheckExp(i); } // Need to deal damages ! thrownObj->flags &= ~ATO_MOVING; thrownObj->velocity = 0.f; need_kill = 1; precision = 500.f; j = 200; } } } } } } if(need_kill) ARX_THROWN_OBJECT_Kill(i); } } } }
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; }
//----------------------------------------------------------------------------- void CMultiMagicMissile::Create(EERIE_3D aePos, EERIE_3D angles) { long lMax = 0; if (pTab) { float afAlpha = angles.a; float afBeta = angles.b; spells[spellinstance].hand_group = GetActionPointIdx(inter.iobj[spells[spellinstance].caster]->obj, "PRIMARY_ATTACH"); if (spells[spellinstance].hand_group != -1) { spells[spellinstance].hand_pos.x = inter.iobj[spells[spellinstance].caster]->obj->vertexlist3[spells[spellinstance].hand_group].v.x; spells[spellinstance].hand_pos.y = inter.iobj[spells[spellinstance].caster]->obj->vertexlist3[spells[spellinstance].hand_group].v.y; spells[spellinstance].hand_pos.z = inter.iobj[spells[spellinstance].caster]->obj->vertexlist3[spells[spellinstance].hand_group].v.z; } if (spells[spellinstance].caster == 0) // player { afBeta = player.angle.b; afAlpha = player.angle.a; EERIE_3D vector; vector.x = -EEsin(DEG2RAD(afBeta)) * EEcos(DEG2RAD(afAlpha)) * 60.f; vector.y = EEsin(DEG2RAD(afAlpha)) * 60.f; vector.z = EEcos(DEG2RAD(afBeta)) * EEcos(DEG2RAD(afAlpha)) * 60.f; if (spells[spellinstance].hand_group != -1) { aePos.x = spells[spellinstance].hand_pos.x + vector.x; aePos.y = spells[spellinstance].hand_pos.y + vector.y; aePos.z = spells[spellinstance].hand_pos.z + vector.z; } else { aePos.x = player.pos.x - EEsin(DEG2RAD(afBeta)) + vector.x; aePos.y = player.pos.y + vector.y; //; aePos.z = player.pos.z + EEcos(DEG2RAD(afBeta)) + vector.z; } } else { afAlpha = 0; afBeta = inter.iobj[spells[spellinstance].caster]->angle.b; EERIE_3D vector; vector.x = -EEsin(DEG2RAD(afBeta)) * EEcos(DEG2RAD(afAlpha)) * 60; vector.y = EEsin(DEG2RAD(afAlpha)) * 60; vector.z = EEcos(DEG2RAD(afBeta)) * EEcos(DEG2RAD(afAlpha)) * 60; if (spells[spellinstance].hand_group != -1) { aePos.x = spells[spellinstance].hand_pos.x + vector.x; aePos.y = spells[spellinstance].hand_pos.y + vector.y; aePos.z = spells[spellinstance].hand_pos.z + vector.z; } else { aePos.x = inter.iobj[spells[spellinstance].caster]->pos.x + vector.x; aePos.y = inter.iobj[spells[spellinstance].caster]->pos.y + vector.y; aePos.z = inter.iobj[spells[spellinstance].caster]->pos.z + vector.z; } INTERACTIVE_OBJ * io = inter.iobj[spells[spellinstance].caster]; if (ValidIONum(io->targetinfo)) { EERIE_3D * p1 = &spells[spellinstance].caster_pos; EERIE_3D * p2 = &inter.iobj[io->targetinfo]->pos; afAlpha = -(RAD2DEG(GetAngle(p1->y, p1->z, p2->y, p2->z + TRUEDistance2D(p2->x, p2->z, p1->x, p1->z)))); //alpha entre orgn et dest; } else if (ValidIONum(spells[spellinstance].target)) { EERIE_3D * p1 = &spells[spellinstance].caster_pos; EERIE_3D * p2 = &inter.iobj[spells[spellinstance].target]->pos; afAlpha = -(RAD2DEG(GetAngle(p1->y, p1->z, p2->y, p2->z + TRUEDistance2D(p2->x, p2->z, p1->x, p1->z)))); //alpha entre orgn et dest; } } for (UINT i = 0 ; i < uiNumber ; i++) { if (pTab[i]) { EERIE_3D angles; angles.a = afAlpha; angles.b = afBeta; angles.g = 0; if (i > 0) { angles.a += frand2() * 4.0f; angles.b += frand2() * 6.0f; } pTab[i]->Create(aePos, angles); float fTime = ulDuration + frand2() * 1000.0f; ARX_CHECK_LONG(fTime); long lTime = ARX_CLEAN_WARN_CAST_LONG(fTime); lTime = max(1000, lTime); lMax = max(lMax, lTime); CMagicMissile * pMM = (CMagicMissile *)pTab[i]; pMM->SetDuration(lTime); if ((spells[spellinstance].caster == 0) && (cur_mr == 3)) { pMM->SetColor(0.9f, 0.2f, 0.5f); pMM->SetColor1(0.9f, 0.2f, 0.5f); } else { pMM->SetColor(0.9f + rnd() * 0.1f, 0.9f + rnd() * 0.1f, 0.7f + rnd() * 0.3f); pMM->SetColor1(0.9f + rnd() * 0.1f, 0.9f + rnd() * 0.1f, 0.7f + rnd() * 0.3f); } pTab[i]->lLightId = GetFreeDynLight(); if (pTab[i]->lLightId != -1) { EERIE_LIGHT * el = &DynLight[pTab[i]->lLightId]; el->exist = 1; el->intensity = 0.7f + 2.3f; el->fallend = 190.f; el->fallstart = 80.f; if ((spells[spellinstance].caster == 0) && (cur_mr == 3)) { el->rgb.r = 1; el->rgb.g = 0.3f; el->rgb.b = 0.8f; } else { el->rgb.r = 0; el->rgb.g = 0; el->rgb.b = 1; } el->pos.x = pMM->eSrc.x; el->pos.y = pMM->eSrc.y; el->pos.z = pMM->eSrc.z; el->duration = 300; } } } } SetDuration(lMax + 1000); }
void CurePoisonSpell::Launch() { if(m_caster == PlayerEntityHandle) { m_target = PlayerEntityHandle; } float cure = m_level * 10; if(m_target == PlayerEntityHandle) { player.poison -= std::min(player.poison, cure); ARX_SOUND_PlaySFX(SND_SPELL_CURE_POISON); } else if (ValidIONum(m_target)) { Entity * io = entities[m_target]; if(io->ioflags & IO_NPC) { io->_npcdata->poisonned -= std::min(io->_npcdata->poisonned, cure); } ARX_SOUND_PlaySFX(SND_SPELL_CURE_POISON, &io->pos); } m_duration = 3500; { ParticleParams cp; cp.m_nbMax = 350; cp.m_life = 800; cp.m_lifeRandom = 2000; cp.m_pos = Vec3f(100, 0, 100); cp.m_direction = Vec3f(0.f, -1.f, 0.f); cp.m_angle = glm::radians(5.f); cp.m_speed = 120; cp.m_speedRandom = 84; cp.m_gravity = Vec3f(0, -10, 0); cp.m_flash = 0; cp.m_rotation = 1.0f / (101 - 80); cp.m_startSegment.m_size = 8;//6; cp.m_startSegment.m_sizeRandom = 8; cp.m_startSegment.m_color = Color(20, 205, 20, 245).to<float>(); cp.m_startSegment.m_colorRandom = Color(50, 50, 50, 10).to<float>(); cp.m_endSegment.m_size = 6; cp.m_endSegment.m_sizeRandom = 4; cp.m_endSegment.m_color = Color(5, 20, 5, 0).to<float>(); cp.m_endSegment.m_colorRandom = Color(0, 40, 0, 0).to<float>(); cp.m_blendMode = RenderMaterial::Additive; cp.m_texture.set("graph/particles/cure_poison", 0, 100); //5 cp.m_spawnFlags = PARTICLE_CIRCULAR | PARTICLE_BORDER; pPS.SetParams(cp); } m_light = GetFreeDynLight(); if(lightHandleIsValid(m_light)) { EERIE_LIGHT * light = lightHandleGet(m_light); light->intensity = 1.5f; light->fallstart = 200.f; light->fallend = 350.f; light->rgb = Color3f(0.f, 1.f, 0.0f); light->pos = m_pos + Vec3f(0.f, -50.f, 0.f); light->time_creation = (unsigned long)(arxtime); light->duration = 200; light->extras = 0; } }
//----------------------------------------------------------------------------- void CFireBall::Update(unsigned long aulTime) { ulCurrentTime += aulTime; if(ulCurrentTime > MIN_TIME_FIREBALL) { // smoke en retard pPSSmoke.SetPos(eCurPos); pPSSmoke.Update(aulTime); eCurPos += eMove * (aulTime * 0.0045f); pPSFire.SetPos(eCurPos); pPSFire.fParticleSpeed = 100; pPSFire.fParticleSpeedRandom = 200; pPSFire.p3ParticleGravity = -eMove * 2.f; pPSFire2.p3ParticleGravity = -eMove * 2.f; pPSFire2.SetPos(eCurPos); pPSFire2.fParticleSpeed = 100; pPSFire2.fParticleSpeedRandom = 100; } else { float afAlpha = 0.f; if (spells[spellinstance].caster == 0) { SetAngle(player.angle.b); afAlpha = player.angle.a; long idx = GetGroupOriginByName(entities[spells[spellinstance].caster]->obj, "chest"); if (idx) { eCurPos.x = entities[spells[spellinstance].caster]->obj->vertexlist3[idx].v.x - fBetaRadSin * 60; eCurPos.y = entities[spells[spellinstance].caster]->obj->vertexlist3[idx].v.y; eCurPos.z = entities[spells[spellinstance].caster]->obj->vertexlist3[idx].v.z + fBetaRadCos * 60; } else { eCurPos.x = player.pos.x - fBetaRadSin * 60; eCurPos.y = player.pos.y; eCurPos.z = player.pos.z + fBetaRadCos * 60; } } else { SetAngle(entities[spells[spellinstance].caster]->angle.b); eCurPos.x = entities[spells[spellinstance].caster]->pos.x - fBetaRadSin * 60; eCurPos.y = entities[spells[spellinstance].caster]->pos.y; eCurPos.z = entities[spells[spellinstance].caster]->pos.z + fBetaRadCos * 60; if ((ValidIONum(spells[spellinstance].caster)) && (entities[spells[spellinstance].caster]->ioflags & IO_NPC)) { eCurPos.x -= EEsin(radians(entities[spells[spellinstance].caster]->angle.b)) * 30.f; eCurPos.y -= 80.f; eCurPos.z += EEcos(radians(entities[spells[spellinstance].caster]->angle.b)) * 30.f; } Entity * io = entities[spells[spellinstance].caster]; if (ValidIONum(io->targetinfo)) { Vec3f * p1 = &eCurPos; Vec3f p2 = entities[io->targetinfo]->pos; p2.y -= 60.f; afAlpha = 360.f - (degrees(getAngle(p1->y, p1->z, p2.y, p2.z + dist(Vec2f(p2.x, p2.z), Vec2f(p1->x, p1->z))))); //alpha entre orgn et dest; } } eMove.x = - fBetaRadSin * 100 * cos(radians(MAKEANGLE(afAlpha))); eMove.y = sin(radians(MAKEANGLE(afAlpha))) * 100; eMove.z = + fBetaRadCos * 100 * cos(radians(MAKEANGLE(afAlpha))); Vec3f vMove = eMove.getNormalized(); // smoke en retard pPSSmoke.p3ParticleDirection = -vMove; pPSSmoke.SetPos(eCurPos); pPSSmoke.RecomputeDirection(); eCurPos = eCurPos + eMove * (aulTime * 0.0045f); pPSFire.p3ParticleDirection = -vMove; pPSFire.RecomputeDirection(); pPSFire.SetPos(eCurPos); pPSFire.p3ParticleGravity = -eMove * 2.f; pPSFire2.p3ParticleDirection = -vMove; pPSFire2.p3ParticleGravity = -eMove * 2.f; pPSFire2.RecomputeDirection(); pPSFire2.SetPos(eCurPos); } pPSFire.Update(aulTime); pPSFire2.Update(aulTime); }
void DANAE_DEBUGGER_Update() { static INTERACTIVE_OBJ * lastio = NULL; static long MODIFFF = 1; if (!DD_Exists) return; if (!DD_Exists()) return; int i; char buffer[20]; ScriptDebuggerUpdate su; memset(&su, 0, sizeof(ScriptDebuggerUpdate)); char p1[256]; char p2[256]; char p3[256]; char p4[256]; su.globalVar.lpszVarName = p1; su.globalVar.lpszVarValue = p2; su.localVar.lpszVarName = p3; su.localVar.lpszVarValue = p4; DD_GetParams(su); ScriptDebuggerInfos s; memset(&s, 0, sizeof(ScriptDebuggerInfos)); INTERACTIVE_OBJ * io; if (ValidIONum(LastSelectedIONum)) io = inter.iobj[LastSelectedIONum]; else io = NULL; IO_DEBUG = io; if (lastio != io) { NEED_DEBUGGER_CLEAR = 1; memset(&s, 0, sizeof(ScriptDebuggerInfos)); s.lpszObjName = strdup("No Object Selected"); DD_SetParams(s); free(s.lpszObjName); MODIFFF = 1; } lastio = io; if (NEED_DEBUGGER_CLEAR) { s.bClear = 1; NEED_DEBUGGER_CLEAR = 0; } if (LastSelectedIONum < 0) { memset(&s, 0, sizeof(ScriptDebuggerInfos)); s.lpszObjName = strdup("No Object Selected"); DD_SetParams(s); free(s.lpszObjName); goto suite; } if ((ARXPausedTimer) && (!MODIFFF)) goto suite; MODIFFF = 0; char temp[256]; sprintf(temp, "%s_%04d", GetName(io->filename), io->ident); s.lpszObjName = strdup(temp); sprintf(buffer, "%5.0f", io->pos.x); s.p3ObjPos[0] = strdup(buffer); sprintf(buffer, "%5.0f", io->pos.y); s.p3ObjPos[1] = strdup(buffer); sprintf(buffer, "%5.0f", io->pos.z); s.p3ObjPos[2] = strdup(buffer); INTERACTIVE_OBJ * tio; tio = NULL; if (ValidIONum(io->targetinfo)) tio = inter.iobj[io->targetinfo]; else if (io->targetinfo == -2) tio = io; if (tio) { sprintf(temp, "%s_%04d", GetName(tio->filename), tio->ident); s.lpszTargetName = strdup(temp); sprintf(buffer, "%5.0f", tio->pos.x); s.p3TargetPos[0] = strdup(buffer); sprintf(buffer, "%5.0f", tio->pos.y); s.p3TargetPos[1] = strdup(buffer); sprintf(buffer, "%5.0f", tio->pos.z); s.p3TargetPos[2] = strdup(buffer); } else { s.lpszTargetName = strdup("None"); s.p3TargetPos[0] = strdup(" "); s.p3TargetPos[1] = strdup(" "); s.p3TargetPos[2] = strdup(" "); } if (su.bVariables) { s.iNbGlobals = NB_GLOBALS; Vars * vg; vg = NULL; if (s.iNbGlobals) { vg = new Vars[s.iNbGlobals]; for (i = 0; i < s.iNbGlobals; i++) { vg[i].lpszVarName = strdup(svar[i].name); switch (svar[i].type) { case TYPE_G_TEXT: vg[i].lpszVarValue = strdup(svar[i].text); break; case TYPE_G_LONG: sprintf(temp, "%d", svar[i].ival); vg[i].lpszVarValue = strdup(temp); break; case TYPE_G_FLOAT: sprintf(temp, "%f", svar[i].fval); vg[i].lpszVarValue = strdup(temp); break; default: sprintf(temp, " "); vg[i].lpszVarValue = strdup(temp); break; } } } s.pGlobalVars = vg; EERIE_SCRIPT * es; es = &io->script; s.iNbLocals = es->nblvar; Vars * vl; vl = NULL; if (s.iNbLocals) { vl = new Vars[s.iNbLocals]; for (i = 0; i < s.iNbLocals; i++) { vl[i].lpszVarName = strdup(es->lvar[i].name); switch (es->lvar[i].type) { case TYPE_L_TEXT: sprintf(temp, "%s", es->lvar[i].text); vl[i].lpszVarValue = strdup(temp); break; case TYPE_L_LONG: sprintf(temp, "%d", es->lvar[i].ival); vl[i].lpszVarValue = strdup(temp); break; case TYPE_L_FLOAT: sprintf(temp, "%f", es->lvar[i].fval); vl[i].lpszVarValue = strdup(temp); break; default: sprintf(temp, " "); vl[i].lpszVarValue = strdup(temp); break; } } } s.pLocalVars = vl; } if (io->ioflags & IO_NPC) { if (io->_npcdata->behavior & BEHAVIOUR_MOVE_TO) strcpy(temp, "MOVE_TO"); else if (io->_npcdata->behavior & BEHAVIOUR_GO_HOME) strcpy(temp, "GO_HOME"); else if (io->_npcdata->behavior & BEHAVIOUR_FLEE) strcpy(temp, "FLEE"); else if (io->_npcdata->behavior & BEHAVIOUR_LOOK_FOR) strcpy(temp, "LOOK_FOR"); else if (io->_npcdata->behavior & BEHAVIOUR_HIDE) strcpy(temp, "HIDE"); else if (io->_npcdata->behavior & BEHAVIOUR_WANDER_AROUND) strcpy(temp, "WANDER_AROUND"); else if (io->_npcdata->behavior & BEHAVIOUR_GUARD) strcpy(temp, "GUARD"); else if (io->_npcdata->behavior & BEHAVIOUR_FRIENDLY) strcpy(temp, "FRIENDLY"); else strcpy(temp, "NONE"); if (io->_npcdata->behavior & BEHAVIOUR_LOOK_AROUND) strcat(temp, " Look_Around"); if (io->_npcdata->behavior & BEHAVIOUR_SNEAK) strcat(temp, " Sneak"); if (io->_npcdata->behavior & BEHAVIOUR_DISTANT) strcat(temp, " Distant"); if (io->_npcdata->behavior & BEHAVIOUR_FIGHT) strcat(temp, " Fight"); if (io->_npcdata->behavior & BEHAVIOUR_MAGIC) strcat(temp, " Magic"); s.lpszBehavior = strdup(temp); } else { s.lpszBehavior = strdup("Not an NPC..."); } s.bEvents = false; if (su.bEvents) { s.bEvents = true; s.lpszEvents = (char *) malloc(BIG_DEBUG_POS + 1); memcpy(s.lpszEvents, BIG_DEBUG_STRING, BIG_DEBUG_POS + 1); BIG_DEBUG_POS = 0; BIG_DEBUG_STRING[0] = 0; } long count; count = 0; for (i = 0; i < MAX_TIMER_SCRIPT; i++) { if ((scr_timer[i].exist) && (scr_timer[i].io == io)) count++; } s.bTimers = false; s.lpszTimers = NULL; if (su.bTimers) { s.bTimers = true; char buf[16000]; ZeroMemory(buf, 16000); long num; num = 0; for (i = 0; i < MAX_TIMER_SCRIPT; i++) { if ((scr_timer[i].exist) && (scr_timer[i].io == io)) { sprintf(temp, "%s %d %dms\r\n", scr_timer[i].name, scr_timer[i].times, scr_timer[i].msecs); strcat(buf, temp); } } s.lpszTimers = strdup(buf); } DD_SetParams(s); if (s.lpszObjName) free(s.lpszObjName); if (s.p3ObjPos[0]) free(s.p3ObjPos[0]); if (s.p3ObjPos[1]) free(s.p3ObjPos[1]); if (s.p3ObjPos[2]) free(s.p3ObjPos[2]); if (s.lpszTargetName) free(s.lpszTargetName); if (s.p3TargetPos[0]) free(s.p3TargetPos[0]); if (s.p3TargetPos[1]) free(s.p3TargetPos[1]); if (s.p3TargetPos[2]) free(s.p3TargetPos[2]); if (su.bVariables) { for (i = 0; i < s.iNbGlobals; i++) { if (s.pGlobalVars[i].lpszVarName) free(s.pGlobalVars[i].lpszVarName); if (s.pGlobalVars[i].lpszVarValue) free(s.pGlobalVars[i].lpszVarValue); } if (s.iNbGlobals) delete [] s.pGlobalVars; for (i = 0; i < s.iNbLocals; i++) { if (s.pLocalVars[i].lpszVarName) free(s.pLocalVars[i].lpszVarName); if (s.pLocalVars[i].lpszVarValue) free(s.pLocalVars[i].lpszVarValue); } if (s.iNbLocals) delete [] s.pLocalVars; } if (s.lpszBehavior) free(s.lpszBehavior); if (s.bEvents) { if (s.lpszEvents) free(s.lpszEvents); } if (s.bTimers) { if (s.lpszTimers) free(s.lpszTimers); } suite: ; if (su.bPause) { if (!ARXPausedTimer) { ARX_TIME_Pause(); } else { ARX_TIME_UnPause(); } } if (su.bStep) { if (ARXPausedTimer) { ARXTotalPausedTime -= 100; MODIFFF = 1; } } if (su.bUpdateGlobalVar) { ARX_SCRIPT_SetVar(NULL, su.globalVar.lpszVarName, su.globalVar.lpszVarValue); MODIFFF = 1; } if ((su.bUpdateLocalVar) && (io)) { ARX_SCRIPT_SetVar(io, su.localVar.lpszVarName, su.localVar.lpszVarValue); MODIFFF = 1; } }
//! \brief Recreates player mesh from scratch static void applyTweak(EquipmentSlot equip, TweakType tw, const std::string & selection) { if(!ValidIONum(player.equiped[equip])) { return; } Entity * io = entities.player(); arx_assert(entities[player.equiped[equip]]->tweakerinfo != NULL); const IO_TWEAKER_INFO & tweak = *entities[player.equiped[equip]]->tweakerinfo; if(!tweak.filename.empty()) { res::path mesh = "graph/obj3d/interactive/npc/human_base/tweaks" / tweak.filename; EERIE_MESH_TWEAK_Do(io, tw, mesh); } if(tweak.skintochange.empty() || tweak.skinchangeto.empty()) { return; } res::path file = "graph/obj3d/textures" / tweak.skinchangeto; TextureContainer * temp = TextureContainer::Load(file, TextureContainer::Level); long mapidx = ObjectAddMap(io->obj, temp); ObjSelection sel = ObjSelection(); for(size_t i = 0; i < io->obj->selections.size(); i++) { if(io->obj->selections[i].name == selection) { sel = ObjSelection(i); break; } } if(sel == ObjSelection()) { return; } long textochange = -1; for(size_t i = 0; i < io->obj->texturecontainer.size(); i++) { if(tweak.skintochange == io->obj->texturecontainer[i]->m_texName.filename()) { textochange = i; } } if(textochange == -1) { return; } for(size_t i = 0; i < io->obj->facelist.size(); i++) { EERIE_FACE & face = io->obj->facelist[i]; if( IsInSelection(io->obj, face.vid[0], sel) && IsInSelection(io->obj, face.vid[1], sel) && IsInSelection(io->obj, face.vid[2], sel) ) { if(face.texid == textochange) { face.texid = (short)mapidx; } } } }
bool DoSphericDamage(const Vec3f & pos, float dmg, float radius, DamageArea flags, DamageType typ, EntityHandle numsource) { bool damagesdone = false; if(radius <= 0.f) return damagesdone; float rad = 1.f / radius; bool validsource = ValidIONum(numsource); for(size_t i = 0; i < entities.size(); i++) { const EntityHandle handle = EntityHandle(i); Entity * ioo = entities[handle]; if(!ioo || long(i) == numsource || !ioo->obj) continue; if ((i != 0) && (numsource != PlayerEntityHandle) && validsource && (HaveCommonGroup(ioo, entities[numsource]))) continue; if((ioo->ioflags & IO_CAMERA) || (ioo->ioflags & IO_MARKER)) continue; long count = 0; long count2 = 0; float mindist = std::numeric_limits<float>::max(); for(size_t k = 0; k < ioo->obj->vertexlist.size(); k += 1) { if(ioo->obj->vertexlist.size() < 120) { for(size_t kk = 0; kk < ioo->obj->vertexlist.size(); kk += 1) { if(kk != k) { Vec3f posi = (entities[handle]->obj->vertexlist3[k].v + entities[handle]->obj->vertexlist3[kk].v) * 0.5f; float dist = fdist(pos, posi); if(dist <= radius) { count2++; if(dist < mindist) mindist = dist; } } } } { float dist = fdist(pos, entities[handle]->obj->vertexlist3[k].v); if(dist <= radius) { count++; if(dist < mindist) mindist = dist; } } } float ratio = ((float)count / ((float)ioo->obj->vertexlist.size() * ( 1.0f / 2 ))); if(count2 > count) ratio = ((float)count2 / ((float)ioo->obj->vertexlist.size() * ( 1.0f / 2 ))); if(ratio > 2.f) ratio = 2.f; if(ioo->ioflags & IO_NPC) { if(mindist <= radius + 30.f) { switch (flags) { case DAMAGE_AREA: dmg = dmg * (radius + 30 - mindist) * rad; break; case DAMAGE_AREAHALF: dmg = dmg * (radius + 30 - mindist * ( 1.0f / 2 )) * rad; break; case DAMAGE_FULL: break; } if(i == 0) { if(typ & DAMAGE_TYPE_FIRE) { dmg = ARX_SPELLS_ApplyFireProtection(ioo, dmg); ARX_DAMAGES_IgnitIO(entities.player(), dmg); } if(typ & DAMAGE_TYPE_COLD) { dmg = ARX_SPELLS_ApplyColdProtection(ioo, dmg); } ARX_DAMAGES_DamagePlayer(dmg, typ, numsource); ARX_DAMAGES_DamagePlayerEquipment(dmg); } else { if(typ & DAMAGE_TYPE_FIRE) { dmg = ARX_SPELLS_ApplyFireProtection(ioo, dmg * ratio); ARX_DAMAGES_IgnitIO(ioo, dmg); } if(typ & DAMAGE_TYPE_COLD) { dmg = ARX_SPELLS_ApplyColdProtection(ioo, dmg * ratio); } ARX_DAMAGES_DamageNPC(ioo, dmg * ratio, numsource, true, &pos); } if(dmg > 1) damagesdone = true; } } else { if(mindist <= radius + 30.f) { if(typ & DAMAGE_TYPE_FIRE) { dmg = ARX_SPELLS_ApplyFireProtection(ioo, dmg * ratio); ARX_DAMAGES_IgnitIO(entities[handle], dmg); } if(typ & DAMAGE_TYPE_COLD) { dmg = ARX_SPELLS_ApplyColdProtection(ioo, dmg * ratio); } if(entities[handle]->ioflags & IO_FIX) ARX_DAMAGES_DamageFIX(entities[handle], dmg * ratio, numsource, true); if(dmg > 0.2f) damagesdone = true; } } } if (typ & DAMAGE_TYPE_FIRE) CheckForIgnition(pos, radius, 1); return damagesdone; }
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; }
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; } }
//*********************************************************************************************** // 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; }
float ARX_DAMAGES_DealDamages(EntityHandle target, float dmg, EntityHandle source, DamageType flags, Vec3f * pos) { if(!ValidIONum(target) || !ValidIONum(source)) return 0; Entity * io_target = entities[target]; Entity * io_source = entities[source]; float damagesdone; if(flags & DAMAGE_TYPE_PER_SECOND) { dmg = dmg * framedelay * ( 1.0f / 1000 ); } if(target == 0) { if(flags & DAMAGE_TYPE_POISON) { if(rnd() * 100.f > player.m_misc.resistPoison) { damagesdone = dmg; player.poison += damagesdone; } else { damagesdone = 0; } } else { if(flags & DAMAGE_TYPE_DRAIN_MANA) { damagesdone = ARX_DAMAGES_DrainMana(io_target, dmg); } else { ARX_DAMAGES_DamagePlayerEquipment(dmg); damagesdone = ARX_DAMAGES_DamagePlayer(dmg, flags, source); } } if(flags & DAMAGE_TYPE_FIRE) ARX_DAMAGES_IgnitIO(io_target, damagesdone); if(flags & DAMAGE_TYPE_DRAIN_LIFE) ARX_DAMAGES_HealInter(io_source, damagesdone); if(flags & DAMAGE_TYPE_DRAIN_MANA) ARX_DAMAGES_HealManaInter(io_source, damagesdone); if(flags & DAMAGE_TYPE_PUSH) ARX_DAMAGES_PushIO(io_target, source, damagesdone * ( 1.0f / 2 )); if((flags & DAMAGE_TYPE_MAGICAL) && !(flags & (DAMAGE_TYPE_FIRE | DAMAGE_TYPE_COLD))) { damagesdone -= player.m_miscFull.resistMagic * ( 1.0f / 100 ) * damagesdone; damagesdone = std::max(0.0f, damagesdone); } return damagesdone; } else { if(io_target->ioflags & IO_NPC) { if(flags & DAMAGE_TYPE_POISON) { if(rnd() * 100.f > io_target->_npcdata->resist_poison) { damagesdone = dmg; io_target->_npcdata->poisonned += damagesdone; } else { damagesdone = 0; } } else { if(flags & DAMAGE_TYPE_FIRE) { if(rnd() * 100.f <= io_target->_npcdata->resist_fire) dmg = 0; ARX_DAMAGES_IgnitIO(io_target, dmg); } if(flags & DAMAGE_TYPE_DRAIN_MANA) { damagesdone = ARX_DAMAGES_DrainMana(io_target, dmg); } else { damagesdone = ARX_DAMAGES_DamageNPC(io_target, dmg, source, true, pos); } } if(flags & DAMAGE_TYPE_DRAIN_LIFE) ARX_DAMAGES_HealInter(io_source, damagesdone); if(flags & DAMAGE_TYPE_DRAIN_MANA) ARX_DAMAGES_HealManaInter(io_source, damagesdone); if(flags & DAMAGE_TYPE_PUSH) ARX_DAMAGES_PushIO(io_target, source, damagesdone * ( 1.0f / 2 )); if((flags & DAMAGE_TYPE_MAGICAL) && !(flags & (DAMAGE_TYPE_FIRE | DAMAGE_TYPE_COLD))) { damagesdone -= io_target->_npcdata->resist_magic * ( 1.0f / 100 ) * damagesdone; damagesdone = std::max(0.0f, damagesdone); } return damagesdone; } } return 0; }
void ARX_EQUIPMENT_Equip(Entity * target, Entity * toequip) { if(!target || !toequip || target != entities.player()) return; EntityHandle validid = EntityHandle(); for(size_t i = 0; i < entities.size(); i++) { const EntityHandle handle = EntityHandle(i); Entity * e = entities[handle]; if(e == toequip) { validid = handle; break; } } if(validid == EntityHandle()) return; RemoveFromAllInventories(toequip); toequip->show = SHOW_FLAG_ON_PLAYER; // on player if(toequip == DRAGINTER) Set_DragInter(NULL); if(toequip->type_flags & (OBJECT_TYPE_DAGGER | OBJECT_TYPE_1H | OBJECT_TYPE_2H |OBJECT_TYPE_BOW)) { if(ValidIONum(player.equiped[EQUIP_SLOT_WEAPON])) ARX_EQUIPMENT_UnEquip(target, entities[player.equiped[EQUIP_SLOT_WEAPON]]); player.equiped[EQUIP_SLOT_WEAPON] = validid; if(toequip->type_flags & OBJECT_TYPE_BOW) EERIE_LINKEDOBJ_LinkObjectToObject(target->obj, toequip->obj, "weapon_attach", "test", toequip); else EERIE_LINKEDOBJ_LinkObjectToObject(target->obj, toequip->obj, "weapon_attach", "primary_attach", toequip); if((toequip->type_flags & (OBJECT_TYPE_2H | OBJECT_TYPE_BOW)) && ValidIONum(player.equiped[EQUIP_SLOT_SHIELD])) ARX_EQUIPMENT_UnEquip(target, entities[player.equiped[EQUIP_SLOT_SHIELD]]); } else if(toequip->type_flags & OBJECT_TYPE_SHIELD) { if(ValidIONum(player.equiped[EQUIP_SLOT_SHIELD])) ARX_EQUIPMENT_UnEquip(target, entities[player.equiped[EQUIP_SLOT_SHIELD]]); player.equiped[EQUIP_SLOT_SHIELD] = validid; EERIE_LINKEDOBJ_LinkObjectToObject(target->obj, toequip->obj, "shield_attach", "shield_attach", toequip); if(ValidIONum(player.equiped[EQUIP_SLOT_WEAPON])) { if(entities[player.equiped[EQUIP_SLOT_WEAPON]]->type_flags & (OBJECT_TYPE_2H | OBJECT_TYPE_BOW)) ARX_EQUIPMENT_UnEquip(target, entities[player.equiped[EQUIP_SLOT_WEAPON]]); } } else if(toequip->type_flags & OBJECT_TYPE_RING) { // check first, if not already equiped if (!((ValidIONum(player.equiped[EQUIP_SLOT_RING_LEFT]) && (toequip == entities[player.equiped[EQUIP_SLOT_RING_LEFT]])) || (ValidIONum(player.equiped[EQUIP_SLOT_RING_RIGHT]) && (toequip == entities[player.equiped[EQUIP_SLOT_RING_RIGHT]])))) { long willequip = -1; if(player.equiped[EQUIP_SLOT_RING_LEFT] == EntityHandle()) willequip = EQUIP_SLOT_RING_LEFT; if(player.equiped[EQUIP_SLOT_RING_RIGHT] == EntityHandle()) willequip = EQUIP_SLOT_RING_RIGHT; if(willequip == -1) { if(bRing) { if(ValidIONum(player.equiped[EQUIP_SLOT_RING_RIGHT])) ARX_EQUIPMENT_UnEquip(target, entities[player.equiped[EQUIP_SLOT_RING_RIGHT]]); willequip = EQUIP_SLOT_RING_RIGHT; } else { if(ValidIONum(player.equiped[EQUIP_SLOT_RING_LEFT])) ARX_EQUIPMENT_UnEquip(target, entities[player.equiped[EQUIP_SLOT_RING_LEFT]]); willequip = EQUIP_SLOT_RING_LEFT; } bRing = !bRing; } player.equiped[willequip] = validid; } } else if(toequip->type_flags & OBJECT_TYPE_ARMOR) { if(ValidIONum(player.equiped[EQUIP_SLOT_ARMOR])) ARX_EQUIPMENT_UnEquip(target, entities[player.equiped[EQUIP_SLOT_ARMOR]]); player.equiped[EQUIP_SLOT_ARMOR] = validid; } else if(toequip->type_flags & OBJECT_TYPE_LEGGINGS) { if(ValidIONum(player.equiped[EQUIP_SLOT_LEGGINGS])) ARX_EQUIPMENT_UnEquip(target, entities[player.equiped[EQUIP_SLOT_LEGGINGS]]); player.equiped[EQUIP_SLOT_LEGGINGS] = validid; } else if(toequip->type_flags & OBJECT_TYPE_HELMET) { if(ValidIONum(player.equiped[EQUIP_SLOT_HELMET])) ARX_EQUIPMENT_UnEquip(target, entities[player.equiped[EQUIP_SLOT_HELMET]]); player.equiped[EQUIP_SLOT_HELMET] = validid; } if(toequip->type_flags & (OBJECT_TYPE_HELMET | OBJECT_TYPE_ARMOR | OBJECT_TYPE_LEGGINGS)) ARX_EQUIPMENT_RecreatePlayerMesh(); ARX_PLAYER_ComputePlayerFullStats(); }
// 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; }
//TODO Move somewhere else void Cedric_ApplyLightingFirstPartRefactor(Entity *io) { if(!io) return; io->special_color = Color3f::white; float poisonpercent = 0.f; float trappercent = 0.f; float secretpercent = 0.f; if((io->ioflags & IO_NPC) && io->_npcdata->poisonned > 0.f) { poisonpercent = io->_npcdata->poisonned * ( 1.0f / 20 ); if(poisonpercent > 1.f) poisonpercent = 1.f; } if((io->ioflags & IO_ITEM) && io->poisonous > 0.f && io->poisonous_count) { poisonpercent = io->poisonous * (1.0f / 20); if(poisonpercent > 1.f) poisonpercent = 1.f; } if((io->ioflags & IO_FIX) && io->_fixdata->trapvalue > -1) { trappercent = player.TRAP_DETECT - io->_fixdata->trapvalue; if(trappercent > 0.f) { trappercent = 0.6f + trappercent * ( 1.0f / 100 ); trappercent = glm::clamp(trappercent, 0.6f, 1.f); } } if((io->ioflags & IO_FIX) && io->secretvalue > -1) { secretpercent = player.TRAP_SECRET - io->secretvalue; if(secretpercent > 0.f) { secretpercent = 0.6f + secretpercent * ( 1.0f / 100 ); secretpercent = glm::clamp(secretpercent, 0.6f, 1.f); } } if(poisonpercent > 0.f) { io->special_color = Color3f::green; } if(trappercent > 0.f) { io->special_color = Color3f(trappercent, 1.f - trappercent, 1.f - trappercent); } if(secretpercent > 0.f) { io->special_color = Color3f(1.f - secretpercent, 1.f - secretpercent, secretpercent); } if(io->ioflags & IO_FREEZESCRIPT) { io->special_color = Color3f::blue; } if(io->sfx_flag & SFX_TYPE_YLSIDE_DEATH) { if(io->show == SHOW_FLAG_TELEPORTING) { io->sfx_time = io->sfx_time + ArxDurationMs(g_framedelay); if (io->sfx_time >= arxtime.now()) io->sfx_time = arxtime.now(); } else { const ArxDuration elapsed = arxtime.now() - io->sfx_time; if(elapsed > ArxDuration_ZERO) { if(elapsed < ArxDurationMs(3000)) { // 5 seconds to red float ratio = toMs(elapsed) * (1.0f / 3000); io->special_color = Color3f(1.f, 1.f - ratio, 1.f - ratio); io->highlightColor += Color3f(std::max(ratio - 0.5f, 0.f), 0.f, 0.f) * 255; AddRandomSmoke(io, 1); } else if(elapsed < ArxDurationMs(6000)) { // 5 seconds to White float ratio = toMs(elapsed) * (1.0f / 3000); io->special_color = Color3f::red; io->highlightColor += Color3f(std::max(ratio - 0.5f, 0.f), 0.f, 0.f) * 255; AddRandomSmoke(io, 2); } else { // SFX finish io->sfx_time = ArxInstant_ZERO; if(io->ioflags & IO_NPC) { MakePlayerAppearsFX(io); AddRandomSmoke(io, 50); Color3f rgb = io->_npcdata->blood_color.to<float>(); Sphere sp = Sphere(io->pos, 200.f); long count = 6; while(count--) { Sphere splatSphere = Sphere(sp.origin, Random::getf(30.f, 60.f)); PolyBoomAddSplat(splatSphere, rgb, 1); sp.origin.y -= Random::getf(0.f, 150.f); ARX_PARTICLES_Spawn_Splat(sp.origin, 200.f, io->_npcdata->blood_color); sp.origin = io->pos + randomVec3f() * Vec3f(200.f, 20.f,200.f) - Vec3f(100.f, 10.f, 100.f); sp.radius = Random::getf(100.f, 200.f); } EERIE_LIGHT * light = dynLightCreate(); if(light) { light->intensity = Random::getf(0.7f, 2.7f); light->fallend = 600.f; light->fallstart = 400.f; light->rgb = Color3f(1.0f, 0.8f, 0.f); light->pos = io->pos + Vec3f(0.f, -80.f, 0.f); light->duration = ArxDurationMs(600); } if(io->sfx_flag & SFX_TYPE_INCINERATE) { io->sfx_flag &= ~SFX_TYPE_INCINERATE; io->sfx_flag &= ~SFX_TYPE_YLSIDE_DEATH; SpellBase * spell = spells.getSpellOnTarget(io->index(), SPELL_INCINERATE); if(!spell) spell = spells.getSpellOnTarget(io->index(), SPELL_MASS_INCINERATE); if(spell) { spells.endSpell(spell); float damages = 20 * spell->m_level; damages = ARX_SPELLS_ApplyFireProtection(io, damages); if (ValidIONum(spell->m_caster)) ARX_DAMAGES_DamageNPC(io, damages, spell->m_caster, true, &entities[spell->m_caster]->pos); else ARX_DAMAGES_DamageNPC(io, damages, spell->m_caster, true, &io->pos); ARX_SOUND_PlaySFX(SND_SPELL_FIRE_HIT, &io->pos); } } else { io->sfx_flag &= ~SFX_TYPE_YLSIDE_DEATH; ARX_INTERACTIVE_DestroyIOdelayed(io); } } } } } } }