Exemplo n.º 1
0
void Entity::destroy() {
	
	LogDebug("destroying entity " << idString());
	
	if(instance() > 0 && !(ioflags & IO_NOSAVE)) {
		if(scriptload) {
			// In case we previously saved this entity...
			currentSavedGameRemoveEntity(idString());
		} else {
			currentSavedGameStoreEntityDeletion(idString());
		}
	}
	
	if(obj) {
		while(!obj->linked.empty()) {
			if(obj->linked[0].lgroup != ObjVertGroup() && obj->linked[0].obj) {
				Entity * linked = obj->linked[0].io;
				if(linked && ValidIOAddress(linked)) {
					EERIE_LINKEDOBJ_UnLinkObjectFromObject(obj, linked->obj);
					linked->destroy();
				}
			}
		}
	}
	
	delete this;
	
}
Exemplo n.º 2
0
static void removeFlare(FLARES & flare) {
	
	if(flare.io && ValidIOAddress(flare.io)) {
		flare.io->flarecount--;
	}

	lightHandleDestroy(flare.dynlight);
	
	flare.tolive = 0;
	flare.exist = 0;
	flarenum--;
	
}
Exemplo n.º 3
0
static void removeFlare(MagicFlare & flare) {
	
	if(flare.io && ValidIOAddress(flare.io)) {
		flare.io->flarecount--;
	}

	lightHandleDestroy(flare.dynlight);
	
	flare.tolive = 0;
	flare.exist = 0;
	g_magicFlaresCount--;
	
}
Exemplo n.º 4
0
static void ARX_SPEECH_Release(long i) {
	
	if(aspeech[i].exist) {
		
		ARX_SOUND_Stop(aspeech[i].sample);
		
		if(ValidIOAddress(aspeech[i].io) && aspeech[i].io->animlayer[2].cur_anim) {
			AcquireLastAnim(aspeech[i].io);
			aspeech[i].io->animlayer[2].cur_anim = NULL;
		}
		
		aspeech[i].clear();
	}
}
Exemplo n.º 5
0
void ARX_SPEECH_ClearIOSpeech(Entity * io) {
	
	if(!io) {
		return;
	}
	
	for(size_t i = 0; i < MAX_ASPEECH; i++) {
		
		if(!aspeech[i].exist || aspeech[i].io != io) {
			continue;
		}
		
		EERIE_SCRIPT * es = aspeech[i].es;
		Entity * io = aspeech[i].ioscript;
		long scrpos = aspeech[i].scrpos;
		ARX_SPEECH_Release(i);
		
		if(es && ValidIOAddress(io)) {
			ScriptEvent::send(es, SM_EXECUTELINE, "", io, "", scrpos);
		}
	}
}
Exemplo n.º 6
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;
}
Exemplo n.º 7
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;
}
Exemplo n.º 8
0
void ARX_SPEECH_Update() {
	
	unsigned long tim = (unsigned long)(arxtime);

	if(cinematicBorder.isActive() || BLOCK_PLAYER_CONTROLS)
		ARX_CONVERSATION_CheckAcceleratedSpeech();

	for(size_t i = 0; i < MAX_ASPEECH; i++) {
		if(!aspeech[i].exist)
			continue;

		Entity * io = aspeech[i].io;

		// updates animations
		if(io) {
			if(aspeech[i].flags & ARX_SPEECH_FLAG_OFFVOICE)
				ARX_SOUND_RefreshSpeechPosition(aspeech[i].sample);
			else
				ARX_SOUND_RefreshSpeechPosition(aspeech[i].sample, io);

			if((io != entities.player() || (io == entities.player() && EXTERNALVIEW)) && ValidIOAddress(io))
			{
				if(!io->anims[aspeech[i].mood])
					aspeech[i].mood = ANIM_TALK_NEUTRAL;
				
				ANIM_HANDLE * anim = io->anims[aspeech[i].mood];
				if(anim) {
					AnimLayer & layer2 = io->animlayer[2];
					if(layer2.cur_anim != anim || (layer2.flags & EA_ANIMEND)) {
						changeAnimation(io, 2, anim);
					}
				}
			}
		}

		// checks finished speech
		if(tim >= aspeech[i].time_creation + aspeech[i].duration) {
			EERIE_SCRIPT *es = aspeech[i].es;
			Entity *io = aspeech[i].ioscript;
			long scrpos = aspeech[i].scrpos;
			ARX_SPEECH_Release(i);

			if(es && ValidIOAddress(io))
				ScriptEvent::send(es, SM_EXECUTELINE, "", io, "", scrpos);
		}
	}

	for(size_t i = 0; i < MAX_ASPEECH; i++) {
		ARX_SPEECH *speech = &aspeech[i];

		if(!speech->exist)
			continue;

		if(speech->text.empty())
			continue;
		
		if(!cinematicBorder.isActive())
			continue;

		if(CINEMA_DECAL < 100.f)
			continue;

		Vec2i sSize = hFontInBook->getTextSize(speech->text);

		float fZoneClippHeight	=	static_cast<float>(sSize.y * 3);
		float fStartYY			=	100 * g_sizeRatio.y;
		float fStartY			=	static_cast<float>(((int)fStartYY - (int)fZoneClippHeight) >> 1);
		float fDepY				=	((float)g_size.height()) - fStartYY + fStartY - speech->fDeltaY + sSize.y;
		float fZoneClippY		=	fDepY + speech->fDeltaY;

		float fAdd = fZoneClippY + fZoneClippHeight ;

		Rect::Num y = checked_range_cast<Rect::Num>(fZoneClippY);
		Rect::Num h = checked_range_cast<Rect::Num>(fAdd);
		
		Rect clippingRect(0, y+1, g_size.width(), h);
		if(config.video.limitSpeechWidth) {
			s32 w = std::min(g_size.width(), s32(640 * g_sizeRatio.y));
			clippingRect.left = (g_size.width() - w) / 2;
			clippingRect.right = (g_size.width() + w) / 2;
		}
		
		float height = (float)ARX_UNICODE_DrawTextInRect(
							hFontInBook,
							Vec2f(clippingRect.left + 10.f, fDepY + fZoneClippHeight),
							clippingRect.right - 10.f,
							speech->text,
							Color::white,
							&clippingRect);

		GRenderer->SetBlendFunc(Renderer::BlendZero, Renderer::BlendInvSrcColor);
		GRenderer->SetRenderState(Renderer::AlphaBlending, true);
		GRenderer->SetRenderState(Renderer::DepthTest, false);

		EERIEDrawFill2DRectDegrad(Vec2f(0.f, fZoneClippY - 1.f),
		                          Vec2f(static_cast<float>(g_size.width()), fZoneClippY + (sSize.y * 3 / 4)),
		                          0.f, Color::white, Color::black);
		EERIEDrawFill2DRectDegrad(Vec2f(0.f, fZoneClippY + fZoneClippHeight - (sSize.y * 3 / 4)),
		                          Vec2f(static_cast<float>(g_size.width()), fZoneClippY + fZoneClippHeight),
		                          0.f, Color::black, Color::white);

		GRenderer->SetBlendFunc(Renderer::BlendOne, Renderer::BlendZero);
		GRenderer->SetRenderState(Renderer::DepthTest, true);
		GRenderer->SetRenderState(Renderer::AlphaBlending, false);

		height += fZoneClippHeight;

		if(speech->fDeltaY <= height) {
			//vitesse du scroll
			float fDTime;

			if(speech->sample) {
				float duration = ARX_SOUND_GetDuration(speech->sample);
				if(duration == 0.0f) {
					duration = 4000.0f;
				}

				fDTime = (height * framedelay) / duration; //speech->duration;
				float fTimeOneLine = ((float)sSize.y) * fDTime;

				if(((float)speech->iTimeScroll) >= fTimeOneLine) {
					float fResteLine = (float)sSize.y - speech->fPixelScroll;
					float fTimePlus = (fResteLine * framedelay) / duration;
					fDTime -= fTimePlus;
					speech->fPixelScroll = 0.f;
					speech->iTimeScroll = 0;
				}
				speech->iTimeScroll	+= checked_range_cast<int>(framedelay);
			} else {
				fDTime = (height * framedelay) / 4000.0f;
			}

			speech->fDeltaY			+= fDTime;
			speech->fPixelScroll	+= fDTime;
		}
	}
}
Exemplo n.º 9
0
void ARX_MAGICAL_FLARES_Update() {

	if(!flarenum)
		return;

	shinum++;
	if(shinum >= 10) {
		shinum = 1;
	}

	long TICKS = long(arxtime) - FRAMETICKS;
	FRAMETICKS = (unsigned long)(arxtime);
	if(TICKS < 0) {
		return;
	}

	bool key = !GInput->actionPressed(CONTROLS_CUST_MAGICMODE);

	RenderMaterial mat;
	mat.setBlendType(RenderMaterial::Additive);
	
	EERIE_LIGHT * light = lightHandleGet(torchLightHandle);
	
	for(long j = 1; j < 5; j++) {

		TextureContainer * surf;
		switch(j) {
			case 2:  surf = flaretc.lumignon; break;
			case 3:  surf = flaretc.lumignon2; break;
			case 4:  surf = flaretc.plasm; break;
			default: surf = flaretc.shine[shinum]; break;
		}

		mat.setTexture(surf);

		for(size_t i = 0; i < MAX_FLARES; i++) {

			FLARES & flare = magicFlares[i];

			if(!flare.exist || flare.type != j) {
				continue;
			}

			flare.tolive -= float(TICKS * 2);
			if(flare.flags & 1) {
				flare.tolive -= float(TICKS * 4);
			} else if (key) {
				flare.tolive -= float(TICKS * 6);
			}

			float z = (flare.tolive * 0.00025f);
			float s;
			if(flare.type == 1) {
				s = flare.size * 2 * z;
			} else if(flare.type == 4) {
				s = flare.size * 2.f * z + 10.f;
			} else {
				s = flare.size;
			}

			if(flare.tolive <= 0.f || flare.pos.y < -64.f || s < 3.f) {

				if(flare.io && ValidIOAddress(flare.io)) {
					flare.io->flarecount--;
				}

				lightHandleDestroy(flare.dynlight);
				
				flare.exist = 0;
				flarenum--;

				continue;
			}

			if(flare.type == 1 && z < 0.6f)  {
				z = 0.6f;
			}

			Color3f c = flare.rgb * z;
			flare.tv.color = c.toRGB();
			flare.v.p = flare.tv.p;

			light->rgb = componentwise_max(light->rgb, c);

			if(lightHandleIsValid(flare.dynlight)) {
				EERIE_LIGHT * el = lightHandleGet(flare.dynlight);
				el->pos = flare.v.p;
				el->rgb = c;
			}

			mat.setDepthTest(flare.io != NULL);
			
			if(flare.bDrawBitmap) {
				s *= 2.f;
				EERIEAddBitmap(mat, flare.v.p, s, s, surf, Color::fromRGBA(flare.tv.color));
			} else {
				EERIEAddSprite(mat, flare.v.p, s * 0.025f + 1.f,
				               Color::fromRGBA(flare.tv.color), 2.f);
			}

		}
	}

	light->rgb = componentwise_min(light->rgb, Color3f::white);
}
Exemplo n.º 10
0
void ManageCombatModeAnimations() {
	
	arx_assert(entities.player());
	
	if(player.m_aimTime > 0) {
		player.m_aimTime += g_platformTime.lastFrameDuration();
	}
	
	Entity * const io = entities.player();
	
	AnimLayer & layer1 = io->animlayer[1];
	
	ANIM_HANDLE ** alist = io->anims;
	WeaponType weapontype = ARX_EQUIPMENT_GetPlayerWeaponType();
	
	if(weapontype == WEAPON_BARE && LAST_WEAPON_TYPE != weapontype) {
		if(layer1.cur_anim != alist[ANIM_BARE_WAIT]) {
			changeAnimation(io, 1, alist[ANIM_BARE_WAIT]);
			player.m_aimTime = 0;
		}
	}
	
	switch(weapontype) {
		case WEAPON_BARE: { // BARE HANDS PLAYER MANAGEMENT
			if(layer1.cur_anim == alist[ANIM_BARE_WAIT]) {
				player.m_aimTime = 0;
				if(eeMousePressed1()) {
					changeAnimation(io, 1, alist[ANIM_BARE_STRIKE_LEFT_START + player.m_strikeDirection * 3]);
					io->isHit = false;
				}
			}
			
			// Now go for strike cycle...
			for(long j = 0; j < 4; j++) {
				if(layer1.cur_anim == alist[ANIM_BARE_STRIKE_LEFT_START + j * 3] && (layer1.flags & EA_ANIMEND)) {
					changeAnimation(io, 1, alist[ANIM_BARE_STRIKE_LEFT_CYCLE + j * 3], EA_LOOP);
					player.m_aimTime = PlatformDuration::ofRaw(1);
				} else if(layer1.cur_anim == alist[ANIM_BARE_STRIKE_LEFT_CYCLE + j * 3] && !eeMousePressed1()) {
					changeAnimation(io, 1, alist[ANIM_BARE_STRIKE_LEFT + j * 3]);
					strikeSpeak(io);
					SendIOScriptEvent(NULL, io, SM_STRIKE, "bare");
					player.m_weaponBlocked = AnimationDuration::ofRaw(-1); // TODO inband signaling AnimationDuration
					player.m_strikeDirection = 0;
					player.m_aimTime = 0;
				} else if(layer1.cur_anim == alist[ANIM_BARE_STRIKE_LEFT + j * 3]) {
					if(layer1.flags & EA_ANIMEND) {
						changeAnimation(io, 1, alist[ANIM_BARE_WAIT], EA_LOOP);
						player.m_strikeDirection = 0;
						player.m_aimTime = PlatformDuration::ofRaw(1);
						player.m_weaponBlocked = AnimationDuration::ofRaw(-1);
					} else if( layer1.ctime > layer1.currentAltAnim()->anim_time * 0.2f
					        && layer1.ctime < layer1.currentAltAnim()->anim_time * 0.8f
					        && player.m_weaponBlocked == AnimationDuration::ofRaw(-1)) {
						
						ActionPoint id = ActionPoint();
						if(layer1.cur_anim == alist[ANIM_BARE_STRIKE_LEFT]) {
							id = io->obj->fastaccess.left_attach;
						} else { // Strike Right
							id = io->obj->fastaccess.primary_attach;
						}
						
						if(id != ActionPoint()) {
							Sphere sphere;
							sphere.origin = actionPointPosition(io->obj, id);
							sphere.radius = 25.f;
							
							EntityHandle num;
							
							if(CheckAnythingInSphere(sphere, EntityHandle_Player, 0, &num)) {
								float dmgs = (player.m_miscFull.damages + 1) * player.m_strikeAimRatio;
								
								if(ARX_DAMAGES_TryToDoDamage(actionPointPosition(io->obj, id), dmgs, 40, EntityHandle_Player)) {
									player.m_weaponBlocked = layer1.ctime;
								}
								
								ParticleSparkSpawnContinous(sphere.origin, unsigned(dmgs), SpawnSparkType_Success);
								
								if(ValidIONum(num)) {
									static PlatformInstant lastHit = 0;
									PlatformInstant now = g_platformTime.frameStart();
									if(now - lastHit > toPlatformDuration(layer1.ctime)) {
										ARX_SOUND_PlayCollision(entities[num]->material, MATERIAL_FLESH, 1.f, 1.f, sphere.origin, NULL);
										lastHit = now;
									}
								}
							}
						}
					}
				}
			}
			break;
		}
		case WEAPON_DAGGER: { // DAGGER PLAYER MANAGEMENT
			// Waiting and receiving Strike Impulse
			if(layer1.cur_anim == alist[ANIM_DAGGER_WAIT]) {
				player.m_aimTime = 0;
				if(eeMousePressed1()) {
					changeAnimation(io, 1, alist[ANIM_DAGGER_STRIKE_LEFT_START + player.m_strikeDirection * 3]);
					io->isHit = false;
				}
			}
			
			// Now go for strike cycle...
			for(long j = 0; j < 4; j++) {
				if(layer1.cur_anim == alist[ANIM_DAGGER_STRIKE_LEFT_START + j * 3] && (layer1.flags & EA_ANIMEND)) {
					changeAnimation(io, 1, alist[ANIM_DAGGER_STRIKE_LEFT_CYCLE + j * 3], EA_LOOP);
					player.m_aimTime = PlatformDuration::ofRaw(1);
				} else if(layer1.cur_anim == alist[ANIM_DAGGER_STRIKE_LEFT_CYCLE + j * 3] && !eeMousePressed1()) {
					changeAnimation(io, 1, alist[ANIM_DAGGER_STRIKE_LEFT + j * 3]);
					strikeSpeak(io);
					SendIOScriptEvent(NULL, io, SM_STRIKE, "dagger");
					player.m_strikeDirection = 0;
					player.m_aimTime = 0;
				} else if(layer1.cur_anim == alist[ANIM_DAGGER_STRIKE_LEFT + j * 3]) {
					if(   layer1.ctime > layer1.currentAltAnim()->anim_time * 0.3f
					   && layer1.ctime < layer1.currentAltAnim()->anim_time * 0.7f
					) {
						Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]];
						
						if(player.m_weaponBlocked == AnimationDuration::ofRaw(-1)
							&& ARX_EQUIPMENT_Strike_Check(io, weapon, player.m_strikeAimRatio, 0))
						{
							player.m_weaponBlocked = layer1.ctime;
						}
					}
					
					if(layer1.flags & EA_ANIMEND) {
						changeAnimation(io, 1, alist[ANIM_DAGGER_WAIT], EA_LOOP);
						layer1.flags &= ~(EA_PAUSED | EA_REVERSE);
						player.m_strikeDirection = 0;
						player.m_aimTime = PlatformDuration::ofRaw(1);
						player.m_weaponBlocked = AnimationDuration::ofRaw(-1);
					}
					
					if(   player.m_weaponBlocked != AnimationDuration::ofRaw(-1)
					   && layer1.ctime < layer1.currentAltAnim()->anim_time * 0.9f
					) {
						Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]];
						ARX_EQUIPMENT_Strike_Check(io, weapon, player.m_strikeAimRatio, 1);
					}
				}
			}
			break;
		}
		case WEAPON_1H: { // 1HANDED PLAYER MANAGEMENT
			// Waiting and Received Strike Impulse
			if(layer1.cur_anim == alist[ANIM_1H_WAIT]) {
				player.m_aimTime = 0;
				if(eeMousePressed1()) {
					changeAnimation(io, 1, alist[ANIM_1H_STRIKE_LEFT_START + player.m_strikeDirection * 3]);
					io->isHit = false;
				}
			}
			
			// Now go for strike cycle...
			for(long j = 0; j < 4; j++) {
				if(layer1.cur_anim == alist[ANIM_1H_STRIKE_LEFT_START + j * 3] && (layer1.flags & EA_ANIMEND)) {
					changeAnimation(io, 1, alist[ANIM_1H_STRIKE_LEFT_CYCLE + j * 3], EA_LOOP);
					player.m_aimTime = PlatformDuration::ofRaw(1);
				} else if(layer1.cur_anim == alist[ANIM_1H_STRIKE_LEFT_CYCLE + j * 3] && !eeMousePressed1()) {
					changeAnimation(io, 1, alist[ANIM_1H_STRIKE_LEFT + j * 3]);
					strikeSpeak(io);
					SendIOScriptEvent(NULL, io, SM_STRIKE, "1h");
					player.m_strikeDirection = 0;
					player.m_aimTime = 0;
				} else if(layer1.cur_anim == alist[ANIM_1H_STRIKE_LEFT + j * 3]) {
					if(   layer1.ctime > layer1.currentAltAnim()->anim_time * 0.3f
					   && layer1.ctime < layer1.currentAltAnim()->anim_time * 0.7f
					) {
						Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]];
						
						if(player.m_weaponBlocked == AnimationDuration::ofRaw(-1)
							&& ARX_EQUIPMENT_Strike_Check(io, weapon, player.m_strikeAimRatio, 0))
						{
							player.m_weaponBlocked = layer1.ctime;
						}
					}
					
					if(layer1.flags & EA_ANIMEND) {
						changeAnimation(io, 1, alist[ANIM_1H_WAIT], EA_LOOP);
						layer1.flags &= ~(EA_PAUSED | EA_REVERSE);
						player.m_strikeDirection = 0;
						player.m_aimTime = 0;
						player.m_weaponBlocked = AnimationDuration::ofRaw(-1);
					}
					
					if(   player.m_weaponBlocked != AnimationDuration::ofRaw(-1)
					   && layer1.ctime < layer1.currentAltAnim()->anim_time * 0.9f
					) {
						Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]];
						ARX_EQUIPMENT_Strike_Check(io, weapon, player.m_strikeAimRatio, 1);
					}
				}
			}
			break;
		}
		case WEAPON_2H: { // 2HANDED PLAYER MANAGEMENT
			// Waiting and Receiving Strike Impulse
			if(layer1.cur_anim == alist[ANIM_2H_WAIT]) {
				player.m_aimTime = 0;
				if(eeMousePressed1()) {
					changeAnimation(io, 1, alist[ANIM_2H_STRIKE_LEFT_START + player.m_strikeDirection * 3]);
					io->isHit = false;
				}
			}
			
			// Now go for strike cycle...
			for(long j = 0; j < 4; j++) {
				if(layer1.cur_anim == alist[ANIM_2H_STRIKE_LEFT_START + j * 3] && (layer1.flags & EA_ANIMEND)) {
					changeAnimation(io, 1, alist[ANIM_2H_STRIKE_LEFT_CYCLE + j * 3], EA_LOOP);
					player.m_aimTime = PlatformDuration::ofRaw(1);
				} else if(layer1.cur_anim == alist[ANIM_2H_STRIKE_LEFT_CYCLE + j * 3] && !eeMousePressed1()) {
					changeAnimation(io, 1, alist[ANIM_2H_STRIKE_LEFT + j * 3]);
					strikeSpeak(io);
					SendIOScriptEvent(NULL, io, SM_STRIKE, "2h");
					player.m_strikeDirection = 0;
					player.m_aimTime = 0;
				} else if(layer1.cur_anim == alist[ANIM_2H_STRIKE_LEFT + j * 3]) {
					if(   layer1.ctime > layer1.currentAltAnim()->anim_time * 0.3f
					   && layer1.ctime < layer1.currentAltAnim()->anim_time * 0.7f
					) {
						Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]];
						
						if(player.m_weaponBlocked == AnimationDuration::ofRaw(-1)
							&& ARX_EQUIPMENT_Strike_Check(io, weapon, player.m_strikeAimRatio, 0))
						{
							player.m_weaponBlocked = layer1.ctime;
						}
					}
					
					if(layer1.flags & EA_ANIMEND) {
						changeAnimation(io, 1, alist[ANIM_2H_WAIT], EA_LOOP);
						layer1.flags &= ~(EA_PAUSED | EA_REVERSE);
						player.m_strikeDirection = 0;
						player.m_aimTime = 0;
						player.m_weaponBlocked = AnimationDuration::ofRaw(-1);
					}
					
					if(   player.m_weaponBlocked != AnimationDuration::ofRaw(-1)
					   && layer1.ctime < layer1.currentAltAnim()->anim_time * 0.9f
					) {
						Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]];
						ARX_EQUIPMENT_Strike_Check(io, weapon, player.m_strikeAimRatio, 1);
					}
				}
			}
			break;
		}
		case WEAPON_BOW: { // MISSILE PLAYER MANAGEMENT
			if(layer1.cur_anim == alist[ANIM_MISSILE_STRIKE_CYCLE]) {
				player.m_bowAimRatio += bowZoomFromDuration(toMs(g_platformTime.lastFrameDuration()));
				
				if(player.m_bowAimRatio > 1.f)
					player.m_bowAimRatio = 1.f;
			}
			
			// Waiting and Receiving Strike Impulse
			if(layer1.cur_anim == alist[ANIM_MISSILE_WAIT]) {
				player.m_aimTime = PlatformDuration::ofRaw(1);
				
				if(eeMousePressed1() && Player_Arrow_Count() > 0) {
					changeAnimation(io, 1, alist[ANIM_MISSILE_STRIKE_PART_1]);
					io->isHit = false;
				}
			}
			
			if(layer1.cur_anim == alist[ANIM_MISSILE_STRIKE_PART_1] && (layer1.flags & EA_ANIMEND)) {
				player.m_aimTime = 0;
				changeAnimation(io, 1, alist[ANIM_MISSILE_STRIKE_PART_2]);
				EERIE_LINKEDOBJ_LinkObjectToObject(io->obj, arrowobj, "left_attach", "attach", NULL);
			}
			
			// Now go for strike cycle...
			if(layer1.cur_anim == alist[ANIM_MISSILE_STRIKE_PART_2] && (layer1.flags & EA_ANIMEND)) {
				changeAnimation(io, 1, alist[ANIM_MISSILE_STRIKE_CYCLE], EA_LOOP);
				player.m_aimTime = PlatformDuration::ofRaw(1);
			} else if(layer1.cur_anim == alist[ANIM_MISSILE_STRIKE_CYCLE] && !eeMousePressed1()) {
				EERIE_LINKEDOBJ_UnLinkObjectFromObject(io->obj, arrowobj);
				changeAnimation(io, 1, alist[ANIM_MISSILE_STRIKE]);
				SendIOScriptEvent(NULL, io, SM_STRIKE, "bow");
				StrikeAimtime();
				player.m_strikeAimRatio = player.m_bowAimRatio;
				Entity * quiver = Player_Arrow_Count_Decrease();
				float poisonous = 0.f;
				
				if(quiver) {
					poisonous = quiver->poisonous;
					if(quiver->poisonous_count > 0) {
						quiver->poisonous_count--;
						
						if(quiver->poisonous_count <= 0)
							quiver->poisonous = 0;
					}
					
					ARX_DAMAGES_DurabilityLoss(quiver, 1.f);
					
					// TODO is this needed ?, quivers seem to self destruct via script, but maybe not all
					if(ValidIOAddress(quiver) && quiver->durability <= 0.f) {
						ARX_INTERACTIVE_DestroyIOdelayed(quiver);
					}
				}
				
				float aimratio = player.m_strikeAimRatio;
				
				if(sp_max && poisonous < 3.f)
					poisonous = 3.f;
				
				Vec3f orgPos = player.pos + Vec3f(0.f, 40.f, 0.f);
				
				if(io->obj->fastaccess.left_attach != ActionPoint()) {
					orgPos = actionPointPosition(io->obj, io->obj->fastaccess.left_attach);
				}
				
				Anglef orgAngle = player.angle;
				
				PlayerLaunchArrow_Test(aimratio, poisonous, orgPos, orgAngle);
				
				if(sp_max) {
					Anglef angle;
					Vec3f pos = player.pos + Vec3f(0.f, 40.f, 0.f);
					
					angle.setPitch(player.angle.getPitch());
					angle.setYaw(player.angle.getYaw() + 8);
					angle.setRoll(player.angle.getRoll());
					PlayerLaunchArrow_Test(aimratio, poisonous, pos, angle);
					angle.setPitch(player.angle.getPitch());
					angle.setYaw(player.angle.getYaw() - 8);
					PlayerLaunchArrow_Test(aimratio, poisonous, pos, angle);
					angle.setPitch(player.angle.getPitch());
					angle.setYaw(player.angle.getYaw() + 4.f);
					PlayerLaunchArrow_Test(aimratio, poisonous, pos, angle);
					angle.setPitch(player.angle.getPitch());
					angle.setYaw(player.angle.getYaw() - 4.f);
					PlayerLaunchArrow_Test(aimratio, poisonous, pos, angle);
				}
				
				player.m_aimTime = 0;
			} else if(layer1.cur_anim == alist[ANIM_MISSILE_STRIKE]) {
				player.m_bowAimRatio -= bowZoomFromDuration(toMs(g_platformTime.lastFrameDuration()));
				
				if(player.m_bowAimRatio < 0)
					player.m_bowAimRatio = 0;
				
				if(layer1.flags & EA_ANIMEND) {
					player.m_bowAimRatio = 0;
					changeAnimation(io, 1, alist[ANIM_MISSILE_WAIT], EA_LOOP);
					player.m_aimTime = 0;
					player.m_weaponBlocked = AnimationDuration::ofRaw(-1);
					EERIE_LINKEDOBJ_UnLinkObjectFromObject(io->obj, arrowobj);
				}
			}
			break;
		}
	}
	
	LAST_WEAPON_TYPE = weapontype;
}
Exemplo n.º 11
0
void ARX_MAGICAL_FLARES_Draw() {

	if(!flarenum)
		return;

	shinum++;
	if(shinum >= 10) {
		shinum = 1;
	}

	long TICKS = long(arxtime) - FRAMETICKS;
	FRAMETICKS = (unsigned long)(arxtime);
	if(TICKS < 0) {
		return;
	}

	GRenderer->SetRenderState(Renderer::DepthWrite, false);
	GRenderer->SetBlendFunc(Renderer::BlendOne, Renderer::BlendOne);
	GRenderer->SetRenderState(Renderer::AlphaBlending, true);

	bool key = !GInput->actionPressed(CONTROLS_CUST_MAGICMODE);

	for(long j = 1; j < 5; j++) {

		TextureContainer * surf;
		switch(j) {
			case 2:  surf = flaretc.lumignon; break;
			case 3:  surf = flaretc.lumignon2; break;
			case 4:  surf = flaretc.plasm; break;
			default: surf = flaretc.shine[shinum]; break;
		}

		for(long i = 0; i < MAX_FLARES; i++) {

			FLARES & flare = magicFlares[i];

			if(!flare.exist || flare.type != j) {
				continue;
			}

			flare.tolive -= float(TICKS * 2);
			if(flare.flags & 1) {
				flare.tolive -= float(TICKS * 4);
			} else if (key) {
				flare.tolive -= float(TICKS * 6);
			}

			float z = (flare.tolive * 0.00025f);
			float s;
			if(flare.type == 1) {
				s = flare.size * 2 * z;
			} else if(flare.type == 4) {
				s = flare.size * 2.f * z + 10.f;
			} else {
				s = flare.size;
			}

			if(flare.tolive <= 0.f || flare.y < -64.f || s < 3.f) {

				if(flare.io && ValidIOAddress(flare.io)) {
					flare.io->flarecount--;
				}

				if(ValidDynLight(flare.dynlight)) {
					DynLight[flare.dynlight].exist = 0;
				}

				flare.dynlight = -1;
				flare.exist = 0;
				flarenum--;

				continue;
			}

			if(flare.type == 1 && z < 0.6f)  {
				z = 0.6f;
			}

			Color3f c = flare.rgb * z;
			flare.tv.color = c.toBGR();
			flare.v.p = flare.tv.p;

			DynLight[0].rgb = componentwise_max(DynLight[0].rgb, c);

			if(ValidDynLight(flare.dynlight)) {
				EERIE_LIGHT * el = &DynLight[flare.dynlight];
				el->pos = flare.v.p;
				el->rgb = c;
			}

			if(!flare.io) {
				GRenderer->SetRenderState(Renderer::DepthTest, false);
			} else {
				GRenderer->SetRenderState(Renderer::DepthTest, true);
			}

			if(flare.bDrawBitmap) {
				s *= 2.f;
				EERIEDrawBitmap(flare.v.p.x, flare.v.p.y, s, s, flare.v.p.z,
								surf, Color::fromBGRA(flare.tv.color));
			} else {
				EERIEDrawSprite(&flare.v, s * 0.025f + 1.f, surf,
								Color::fromBGRA(flare.tv.color), 2.f);
			}

		}
	}

	DynLight[0].rgb = componentwise_min(DynLight[0].rgb, Color3f::white);

	GRenderer->SetRenderState(Renderer::DepthWrite, true);
	GRenderer->SetRenderState(Renderer::DepthTest, true);
}