예제 #1
0
void NegateMagicSpell::LaunchAntiMagicField() {
	
	if(!ValidIONum(m_target)) {
		return;
	}
	
	for(size_t i = 0; i < MAX_SPELLS; i++) {
		SpellBase * spell = spells[SpellHandle(i)];
		
		if(!spell || 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);
			}
		}
	}
}
예제 #2
0
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;
	}
}
예제 #3
0
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;
}
예제 #5
0
void ManageCombatModeAnimations() {
	arx_assert(entities.player());
		
	Entity * const io = entities.player();
	
	AnimLayer & layer1 = io->animlayer[1];

	ANIM_HANDLE ** alist=io->anims;
	WeaponType weapontype = ARX_EQUIPMENT_GetPlayerWeaponType();
	
	if(weapontype == WEAPON_BARE && LAST_WEAPON_TYPE != weapontype) {
		if(layer1.cur_anim != alist[ANIM_BARE_WAIT]) {
			changeAnimation(io, 1, alist[ANIM_BARE_WAIT]);
			AimTime = 0;
		}
	}
	
	switch(weapontype) {
		case WEAPON_BARE:	// BARE HANDS PLAYER MANAGEMENT

			if(layer1.cur_anim == alist[ANIM_BARE_WAIT]) {
				AimTime = 0;
				if(eeMousePressed1()) {
					changeAnimation(io, 1, alist[ANIM_BARE_STRIKE_LEFT_START + CurrFightPos * 3]);
					io->isHit = false;
				}
			}

			// Now go for strike cycle...
			for(long j = 0; j < 4; j++) {
				if(layer1.cur_anim == alist[ANIM_BARE_STRIKE_LEFT_START+j*3] && (layer1.flags & EA_ANIMEND)) {
					changeAnimation(io, 1, alist[ANIM_BARE_STRIKE_LEFT_CYCLE + j * 3], EA_LOOP);
					AimTime = (unsigned long)(arxtime);
				} else if(layer1.cur_anim == alist[ANIM_BARE_STRIKE_LEFT_CYCLE+j*3] && !eeMousePressed1()) {
					changeAnimation(io, 1, alist[ANIM_BARE_STRIKE_LEFT + j * 3]);
					strikeSpeak(io);
					SendIOScriptEvent(io, SM_STRIKE, "bare");
					PlayerWeaponBlocked = -1;
					CurrFightPos = 0;
					AimTime = 0;
				} else if(layer1.cur_anim == alist[ANIM_BARE_STRIKE_LEFT+j*3]) {
					if(layer1.flags & EA_ANIMEND) {
						changeAnimation(io, 1, alist[ANIM_BARE_WAIT], EA_LOOP);
						CurrFightPos = 0;
						AimTime = (unsigned long)(arxtime);
						PlayerWeaponBlocked = -1;
					} else if(layer1.ctime > layer1.cur_anim->anims[layer1.altidx_cur]->anim_time * 0.2f
							&& layer1.ctime < layer1.cur_anim->anims[layer1.altidx_cur]->anim_time * 0.8f
							&& PlayerWeaponBlocked == -1
					) {
						long id = -1;
						
						if(layer1.cur_anim == alist[ANIM_BARE_STRIKE_LEFT]) {
							id = io->obj->fastaccess.left_attach;
						} else { // Strike Right
							id = io->obj->fastaccess.primary_attach;
						}
						
						if(id != -1) {
							Sphere sphere;
							sphere.origin = io->obj->vertexlist3[id].v;
							sphere.radius = 25.f;
							
							EntityHandle num;
							
							if(CheckAnythingInSphere(sphere, PlayerEntityHandle, 0, &num)) {
								float dmgs = (player.m_miscFull.damages + 1) * STRIKE_AIMTIME;
								
								if(ARX_DAMAGES_TryToDoDamage(io->obj->vertexlist3[id].v, dmgs, 40, PlayerEntityHandle)) {
									PlayerWeaponBlocked = layer1.ctime;
								}
								
								ARX_PARTICLES_Spawn_Spark(sphere.origin, int(dmgs), 2);
								
								if(ValidIONum(num)) {
									ARX_SOUND_PlayCollision(entities[num]->material, MATERIAL_FLESH, 1.f, 1.f, sphere.origin, NULL);
								}
							}
						}
					}
				}
			}

		break;
		case WEAPON_DAGGER: // DAGGER PLAYER MANAGEMENT
			
			// Waiting and receiving Strike Impulse
			if(layer1.cur_anim == alist[ANIM_DAGGER_WAIT]) {
				AimTime = 0;
				if(eeMousePressed1()) {
					changeAnimation(io, 1, alist[ANIM_DAGGER_STRIKE_LEFT_START + CurrFightPos * 3]);
					io->isHit = false;
				}
			}

			// Now go for strike cycle...
			for(long j = 0; j < 4; j++) {
				if(layer1.cur_anim == alist[ANIM_DAGGER_STRIKE_LEFT_START+j*3] && (layer1.flags & EA_ANIMEND)) {
					changeAnimation(io, 1, alist[ANIM_DAGGER_STRIKE_LEFT_CYCLE + j * 3], EA_LOOP);
					AimTime = (unsigned long)(arxtime);
				} else if(layer1.cur_anim == alist[ANIM_DAGGER_STRIKE_LEFT_CYCLE+j*3] && !eeMousePressed1()) {
					changeAnimation(io, 1, alist[ANIM_DAGGER_STRIKE_LEFT + j * 3]);
					strikeSpeak(io);
					SendIOScriptEvent(io, SM_STRIKE, "dagger");
					CurrFightPos = 0;
					AimTime = 0;
				} else if(layer1.cur_anim == alist[ANIM_DAGGER_STRIKE_LEFT+j*3]) {
					if(layer1.ctime > layer1.cur_anim->anims[layer1.altidx_cur]->anim_time * 0.3f
						&& layer1.ctime < layer1.cur_anim->anims[layer1.altidx_cur]->anim_time * 0.7f)
					{
						Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]];
						
						if(PlayerWeaponBlocked == -1
							&& ARX_EQUIPMENT_Strike_Check(io, weapon, STRIKE_AIMTIME, 0))
						{
							PlayerWeaponBlocked = layer1.ctime;
						}
					}

					if(layer1.flags & EA_ANIMEND) {
						changeAnimation(io, 1, alist[ANIM_DAGGER_WAIT], EA_LOOP);
						layer1.flags &= ~(EA_PAUSED | EA_REVERSE);
						CurrFightPos = 0;
						AimTime = (unsigned long)(arxtime);
						PlayerWeaponBlocked = -1;
					}

					if(PlayerWeaponBlocked != -1 && layer1.ctime < layer1.cur_anim->anims[layer1.altidx_cur]->anim_time * 0.9f) {
						Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]];
						ARX_EQUIPMENT_Strike_Check(io, weapon, STRIKE_AIMTIME, 1);
					}
				}
			}

		break;
		case WEAPON_1H: // 1HANDED PLAYER MANAGEMENT
			
			// Waiting and Received Strike Impulse
			if(layer1.cur_anim == alist[ANIM_1H_WAIT]) {
				AimTime = 0;
				if(eeMousePressed1()) {
					changeAnimation(io, 1, alist[ANIM_1H_STRIKE_LEFT_START + CurrFightPos * 3]);
					io->isHit = false;
				}
			}

			// Now go for strike cycle...
			for(long j = 0; j < 4; j++) {
				if(layer1.cur_anim == alist[ANIM_1H_STRIKE_LEFT_START+j*3] && (layer1.flags & EA_ANIMEND)) {
					changeAnimation(io, 1, alist[ANIM_1H_STRIKE_LEFT_CYCLE + j * 3], EA_LOOP);
					AimTime = (unsigned long)(arxtime);
				} else if(layer1.cur_anim == alist[ANIM_1H_STRIKE_LEFT_CYCLE+j*3] && !eeMousePressed1()) {
					changeAnimation(io, 1, alist[ANIM_1H_STRIKE_LEFT + j * 3]);
					strikeSpeak(io);
					SendIOScriptEvent(io, SM_STRIKE, "1h");
					CurrFightPos = 0;
					AimTime = 0;
				} else if(layer1.cur_anim == alist[ANIM_1H_STRIKE_LEFT+j*3]) {
					if(layer1.ctime > layer1.cur_anim->anims[layer1.altidx_cur]->anim_time * 0.3f
						&& layer1.ctime < layer1.cur_anim->anims[layer1.altidx_cur]->anim_time * 0.7f)
					{
						Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]];
						
						if(PlayerWeaponBlocked == -1
							&& ARX_EQUIPMENT_Strike_Check(io, weapon, STRIKE_AIMTIME, 0))
						{
							PlayerWeaponBlocked = layer1.ctime;
						}
					}

					if(layer1.flags & EA_ANIMEND) {
						changeAnimation(io, 1, alist[ANIM_1H_WAIT], EA_LOOP);
						layer1.flags &= ~(EA_PAUSED | EA_REVERSE);
						CurrFightPos = 0;
						AimTime = 0;
						PlayerWeaponBlocked = -1;
					}

					if(PlayerWeaponBlocked != -1 && layer1.ctime < layer1.cur_anim->anims[layer1.altidx_cur]->anim_time * 0.9f) {
						Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]];
						ARX_EQUIPMENT_Strike_Check(io, weapon, STRIKE_AIMTIME, 1);
					}
				}
			}
		break;
		case WEAPON_2H: // 2HANDED PLAYER MANAGEMENT
			
			// Waiting and Receiving Strike Impulse
			if(layer1.cur_anim == alist[ANIM_2H_WAIT]) {
				AimTime = 0;
				if(eeMousePressed1()) {
					changeAnimation(io, 1, alist[ANIM_2H_STRIKE_LEFT_START + CurrFightPos * 3]);
					io->isHit = false;
				}
			}

			// Now go for strike cycle...
			for(long j = 0; j < 4; j++) {
				if(layer1.cur_anim == alist[ANIM_2H_STRIKE_LEFT_START+j*3] && (layer1.flags & EA_ANIMEND)) {
					changeAnimation(io, 1, alist[ANIM_2H_STRIKE_LEFT_CYCLE + j * 3], EA_LOOP);
					AimTime = (unsigned long)(arxtime);
				} else if(layer1.cur_anim == alist[ANIM_2H_STRIKE_LEFT_CYCLE+j*3] && !eeMousePressed1()) {
					changeAnimation(io, 1, alist[ANIM_2H_STRIKE_LEFT + j * 3]);
					strikeSpeak(io);
					SendIOScriptEvent(io, SM_STRIKE, "2h");
					CurrFightPos = 0;
					AimTime = 0;
				} else if(layer1.cur_anim == alist[ANIM_2H_STRIKE_LEFT+j*3]) {
					if(layer1.ctime > layer1.cur_anim->anims[layer1.altidx_cur]->anim_time * 0.3f
						&& layer1.ctime < layer1.cur_anim->anims[layer1.altidx_cur]->anim_time * 0.7f)
					{
						Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]];
						
						if(PlayerWeaponBlocked == -1
							&& ARX_EQUIPMENT_Strike_Check(io, weapon, STRIKE_AIMTIME, 0))
						{
							PlayerWeaponBlocked = layer1.ctime;
						}
					}

					if(layer1.flags & EA_ANIMEND) {
						changeAnimation(io, 1, alist[ANIM_2H_WAIT], EA_LOOP);
						layer1.flags &= ~(EA_PAUSED | EA_REVERSE);
						CurrFightPos = 0;
						AimTime = 0;
						PlayerWeaponBlocked = -1;
					}

					if(PlayerWeaponBlocked != -1 && layer1.ctime < layer1.cur_anim->anims[layer1.altidx_cur]->anim_time * 0.9f) {
						Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]];
						ARX_EQUIPMENT_Strike_Check(io, weapon, STRIKE_AIMTIME, 1);
					}
				}
			}
		break;
		case WEAPON_BOW: // MISSILE PLAYER MANAGEMENT
			if(layer1.cur_anim == alist[ANIM_MISSILE_STRIKE_CYCLE]) {
				if(GLOBAL_SLOWDOWN != 1.f)
					BOW_FOCAL += Original_framedelay;
				else
					BOW_FOCAL += framedelay;

				if(BOW_FOCAL > 710)
					BOW_FOCAL = 710;
			}

			// Waiting and Receiving Strike Impulse
			if(layer1.cur_anim == alist[ANIM_MISSILE_WAIT]) {
				AimTime = (unsigned long)(arxtime);

				if(eeMousePressed1() && Player_Arrow_Count() > 0) {
					changeAnimation(io, 1, alist[ANIM_MISSILE_STRIKE_PART_1]);
					io->isHit = false;
				}
			}

			if(layer1.cur_anim == alist[ANIM_MISSILE_STRIKE_PART_1] && (layer1.flags & EA_ANIMEND)) {
				AimTime = 0;
				changeAnimation(io, 1, alist[ANIM_MISSILE_STRIKE_PART_2]);
				EERIE_LINKEDOBJ_LinkObjectToObject(io->obj, arrowobj, "left_attach", "attach", NULL);
			}

			// Now go for strike cycle...
			if(layer1.cur_anim == alist[ANIM_MISSILE_STRIKE_PART_2] && (layer1.flags & EA_ANIMEND)) {
				changeAnimation(io, 1, alist[ANIM_MISSILE_STRIKE_CYCLE], EA_LOOP);
				AimTime = (unsigned long)(arxtime);
			} else if(layer1.cur_anim == alist[ANIM_MISSILE_STRIKE_CYCLE] && !eeMousePressed1()) {
				EERIE_LINKEDOBJ_UnLinkObjectFromObject(io->obj, arrowobj);
				changeAnimation(io, 1, alist[ANIM_MISSILE_STRIKE]);
				SendIOScriptEvent(io, SM_STRIKE, "bow");
				StrikeAimtime();
				STRIKE_AIMTIME = (float)(BOW_FOCAL)/710.f;
				Entity * quiver = Player_Arrow_Count_Decrease();
				float poisonous = 0.f;

				if(quiver) {
					poisonous = quiver->poisonous;
					if(quiver->poisonous_count > 0) {
						quiver->poisonous_count--;

						if(quiver->poisonous_count <= 0)
							quiver->poisonous = 0;
					}

					ARX_DAMAGES_DurabilityLoss(quiver, 1.f);

					// TODO is this needed ?, quivers seem to self destruct via script, but maybe not all
					if(ValidIOAddress(quiver) && quiver->durability <= 0.f) {
						ARX_INTERACTIVE_DestroyIOdelayed(quiver);
					}
				}

				float aimratio = STRIKE_AIMTIME;

				if(sp_max && poisonous < 3.f)
					poisonous = 3.f;

				Vec3f orgPos = player.pos + Vec3f(0.f, 40.f, 0.f);

				if(io->obj->fastaccess.left_attach >= 0) {
					orgPos = io->obj->vertexlist3[io->obj->fastaccess.left_attach].v;
				}

				Anglef orgAngle = player.angle;

				PlayerLaunchArrow_Test(aimratio, poisonous, orgPos, orgAngle);

				if(sp_max) {
					Anglef angle;
					Vec3f pos = player.pos + Vec3f(0.f, 40.f, 0.f);
					
					angle.setYaw(player.angle.getYaw());
					angle.setPitch(player.angle.getPitch() + 8);
					angle.setRoll(player.angle.getRoll());
					PlayerLaunchArrow_Test(aimratio, poisonous, pos, angle);
					angle.setYaw(player.angle.getYaw());
					angle.setPitch(player.angle.getPitch() - 8);
					PlayerLaunchArrow_Test(aimratio, poisonous, pos, angle);
					angle.setYaw(player.angle.getYaw());
					angle.setPitch(player.angle.getPitch() + 4.f);
					PlayerLaunchArrow_Test(aimratio, poisonous, pos, angle);
					angle.setYaw(player.angle.getYaw());
					angle.setPitch(player.angle.getPitch() - 4.f);
					PlayerLaunchArrow_Test(aimratio, poisonous, pos, angle);
				}

				AimTime = 0;
			} else if(layer1.cur_anim == alist[ANIM_MISSILE_STRIKE]) {
				BOW_FOCAL -= Original_framedelay;

				if(BOW_FOCAL < 0)
					BOW_FOCAL = 0;

				if(layer1.flags & EA_ANIMEND) {
					BOW_FOCAL = 0;
					changeAnimation(io, 1, alist[ANIM_MISSILE_WAIT], EA_LOOP);
					AimTime = 0;
					PlayerWeaponBlocked = -1;
					EERIE_LINKEDOBJ_UnLinkObjectFromObject(io->obj, arrowobj);
				}
			}
		break;
	}

	LAST_WEAPON_TYPE = weapontype;
}
예제 #6
0
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);
}
예제 #7
0
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;
}
예제 #8
0
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);
}
예제 #9
0
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);
}
예제 #10
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;
}
예제 #11
0
//*************************************************************************************
// 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);
}
예제 #13
0
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;
}
예제 #14
0
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();
}
예제 #15
0
//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);
						}
					}
				}
			}
		}
	}
}
예제 #16
0
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);
		}
		}
	}
}
예제 #17
0
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;
}
예제 #18
0
//-----------------------------------------------------------------------------
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);
}
예제 #19
0
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;
	}
}
예제 #20
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);
}
예제 #21
0
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;
	}
}
예제 #22
0
//! \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;
			}
		}
	}
	
}
예제 #23
0
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;
}
예제 #24
0
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;
}
예제 #25
0
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;
	}
}
예제 #26
0
//***********************************************************************************************
// 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;
}
예제 #27
0
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;
}
예제 #28
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();
}
예제 #29
0
// 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;
}
예제 #30
0
//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);
						}
					}
				}
			}
		}
	}
}