Пример #1
0
void MassParalyseSpell::Launch() {
	
	ARX_SOUND_PlaySFX(SND_SPELL_MASS_PARALYSE);
	
	m_duration = (m_launchDuration >= 0) ? m_launchDuration : GameDurationMs(10000);
	m_hasDuration = true;
	
	for(size_t ii = 0; ii < entities.size(); ii++) {
		const EntityHandle handle = EntityHandle(ii);
		Entity * tio = entities[handle];
		
		if(   handle == m_caster
		   || !tio || !(tio->ioflags & IO_NPC)
		   || tio->show != SHOW_FLAG_IN_SCENE
		   || (tio->ioflags & IO_FREEZESCRIPT)
		   || fartherThan(tio->pos, entities[m_caster]->pos, 500.f)
		) {
			continue;
		}
		
		tio->ioflags |= IO_FREEZESCRIPT;
		
		ARX_NPC_Kill_Spell_Launch(tio);
		m_targets.push_back(tio->index());
	}
}
Пример #2
0
void BlessSpell::Launch() {
	
	if(m_caster == EntityHandle_Player) {
		m_target = EntityHandle_Player;
	}
	
	spells.endByCaster(m_target, SPELL_BLESS);
	
	ARX_SOUND_PlaySFX(SND_SPELL_BLESS);
	
	// TODO m_launchDuration is not used
	// m_duration = (m_launchDuration > -1) ? m_launchDuration : 2000000;
	m_duration = GameDurationMs(20000);
	m_hasDuration = true;
	m_fManaCostPerSecond = 0.3333f * m_level;
	
	m_pos = entities[m_caster]->pos;
	
	m_yaw = 0.f;
	m_scale = 0.f;
	fRot = 0.f;
	
	tex_p1 = TextureContainer::Load("graph/obj3d/textures/(fx)_tsu_blueting");
	tex_sol = TextureContainer::Load("graph/particles/(fx)_pentagram_bless");
	
	m_targets.push_back(m_target);
}
Пример #3
0
void ColdProtectionSpell::Launch() {
	
	spells.endByTarget(m_target, SPELL_COLD_PROTECTION);
	spells.endByCaster(m_caster, SPELL_ARMOR);
	spells.endByCaster(m_caster, SPELL_LOWER_ARMOR);
	spells.endByCaster(m_caster, SPELL_FIRE_PROTECTION);
	
	if(m_caster == EntityHandle_Player) {
		m_target = EntityHandle_Player;
	}
	
	ARX_SOUND_PlaySFX(SND_SPELL_COLD_PROTECTION_START, &entities[m_target]->pos);
	
	if(m_caster == EntityHandle_Player) {
		m_duration = 0;
		m_hasDuration = false;
	} else {
		m_duration = (m_launchDuration >= 0) ? m_launchDuration : GameDurationMs(20000);
		m_hasDuration = true;
	}
	
	m_fManaCostPerSecond = 1.f;
	
	Entity * io = entities.get(m_target);
	if(io) {
		io->halo.flags = HALO_ACTIVE;
		io->halo.color = Color3f(0.2f, 0.2f, 0.45f);
		io->halo.radius = 45.f;
	}
	
	m_snd_loop = ARX_SOUND_PlaySFX(SND_SPELL_COLD_PROTECTION_LOOP, &entities[m_target]->pos, 1.f, ARX_SOUND_PLAY_LOOPED);
	
	m_targets.push_back(m_target);
}
Пример #4
0
void SummonCreatureSpell::End() {
	
	lightHandleDestroy(m_light);
	// need to killio
	
	Entity * io = entities.get(m_summonedEntity);
	if(io) {
		ARX_SOUND_PlaySFX(SND_SPELL_ELECTRIC, &io->pos);
		
		if(io->scriptload && (io->ioflags & IO_NOSAVE)) {
			
			AddRandomSmoke(io, 100);
			Vec3f posi = io->pos;
			posi.y -= 100.f;
			MakeCoolFx(posi);
		
			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.0f);
				light->pos = posi;
				light->duration = GameDurationMs(600);
			}
			
			io->destroyOne();
		}
	}
	
	m_summonedEntity = EntityHandle();
}
Пример #5
0
void CurePoisonSpell::Update() {
	
	m_pos = entities[m_target]->pos;
	
	if(m_target == EntityHandle_Player)
		m_pos.y += 200;
	
	GameDuration ff = m_duration - m_elapsed;
	
	if(ff < GameDurationMs(1500)) {
		m_particles.m_parameters.m_spawnFlags = PARTICLE_CIRCULAR;
		m_particles.m_parameters.m_gravity = Vec3f(0.f);

		std::list<Particle *>::iterator i;

		for(i = m_particles.listParticle.begin(); i != m_particles.listParticle.end(); ++i) {
			Particle * pP = *i;

			if(pP->isAlive()) {
				pP->fColorEnd.a = 0;

				if(pP->m_age + ff < pP->m_timeToLive) {
					pP->m_age = pP->m_timeToLive - ff;
				}
			}
		}
	}

	m_particles.SetPos(m_pos);
	m_particles.Update(g_gameTime.lastFrameDuration());
	
	EERIE_LIGHT * light = dynLightCreate(m_light);
	if(light) {
		light->intensity = 2.3f;
		light->fallstart = 200.f;
		light->fallend   = 350.f;
		light->rgb = Color3f(0.4f, 1.f, 0.4f);
		light->pos = m_pos + Vec3f(0.f, -50.f, 0.f);
		light->duration = GameDurationMs(200);
		light->creationTime = g_gameTime.now();
		light->extras = 0;
	}
	
	m_particles.Render();
}
Пример #6
0
void NegateMagicSpell::Update() {
	
	LaunchAntiMagicField();
	
	if(m_target == EntityHandle_Player) {
		m_pos = player.basePosition();
	} else {
		Entity * target = entities.get(m_target);
		if(target) {
			m_pos = target->pos;
		}
	}
	
	Vec3f stitepos = m_pos - Vec3f(0.f, 10.f, 0.f);
	
	RenderMaterial mat;
	mat.setLayer(RenderMaterial::Decal);
	mat.setDepthTest(true);
	mat.setTexture(tex_sol);
	mat.setBlendType(RenderMaterial::Additive);
	
	for(int i = 0; i < 360; i++) {
		float t = Random::getf();
		if(t < 0.04f) {
			
			PARTICLE_DEF * pd = createParticle();
			if(!pd) {
				break;
			}
			
			pd->ov = stitepos + arx::randomOffsetXZ(150.f);
			pd->move = Vec3f(0.f, Random::getf(-3.f, 0.f), 0.f);
			pd->siz = 0.3f;
			pd->tolive = Random::getu(2000, 4000);
			pd->tc = tex_p2;
			pd->m_flags = FADE_IN_AND_OUT | ROTATING | DISSIPATING | SUBSTRACT;
			pd->m_rotation = 0.0000001f;
		}
	}
	
	float rot = timeWaveSaw(g_gameTime.now(), GameDurationMs(18000)) * 360.f;
	
	Anglef stiteangle(0.f, -rot, 0.f);
	float scalediff = timeWaveSin(g_gameTime.now(), GameDurationMsf(1570.79632f));
	
	{
	Color3f stitecolor = Color3f::gray(.4f);
	Vec3f stitescale = Vec3f(3.f + 0.5f * scalediff);
	Draw3DObject(ssol, stiteangle, stitepos, stitescale, stitecolor, mat);
	}
	
	{
	Color3f stitecolor = Color3f(.5f, 0.f, .5f);
	Vec3f stitescale = Vec3f(3.1f + 0.2f * scalediff);
	Draw3DObject(ssol, stiteangle, stitepos, stitescale, stitecolor, mat);
	}
}
Пример #7
0
void PoisonProjectileSpell::Update() {
	
	for(size_t i = 0; i < m_projectiles.size(); i++) {
		CPoisonProjectile * projectile = m_projectiles[i];
		
		projectile->Update(g_gameTime.lastFrameDuration());
	}
	
	for(size_t i = 0; i < m_projectiles.size(); i++) {
		CPoisonProjectile * projectile = m_projectiles[i];
		
		projectile->Render();
		
		EERIE_LIGHT * light = lightHandleGet(projectile->lLightId);
		if(light) {
			light->intensity = 2.3f * projectile->lightIntensityFactor;
			light->fallend = 250.f;
			light->fallstart = 150.f;
			light->rgb = Color3f::green;
			light->pos = projectile->eCurPos;
			light->creationTime = g_gameTime.now();
			light->duration = GameDurationMs(200);
		}

		AddPoisonFog(projectile->eCurPos, m_level + 7);

		if(m_elapsed > GameDurationMs(1600)) {
			DamageParameters damage;
			damage.pos = projectile->eCurPos;
			damage.radius = 120.f;
			damage.damages = (4.f + m_level * 0.6f) * 0.001f * g_framedelay;
			damage.area = DAMAGE_FULL;
			damage.duration = g_gameTime.lastFrameDuration();
			damage.source = m_caster;
			damage.flags = 0;
			damage.type = DAMAGE_TYPE_MAGICAL | DAMAGE_TYPE_POISON;
			DamageCreate(damage);
		}
		
	}
	
}
Пример #8
0
void PoisonProjectileSpell::End() {
	
	for(size_t i = 0; i < m_projectiles.size(); i++) {
		CPoisonProjectile * projectile = m_projectiles[i];
		
		endLightDelayed(projectile->lLightId, GameDurationMs(2000));
		
		delete projectile;
	}
	m_projectiles.clear();
}
Пример #9
0
void LevitateSpell::Update() {
	
	Vec3f target;

	if(m_target == EntityHandle_Player) {
		target = player.pos + Vec3f(0.f, 150.f, 0.f);
		player.levitate = true;
	} else {
		target = entities[m_caster]->pos;
	}
	
	m_pos = target;
	
	float coneScale = 0.f;
	int dustParticles = 0;
	
	if(m_elapsed < GameDurationMs(1000)) {
		coneScale = m_elapsed / GameDurationMs(1000);
		dustParticles = 3;
	} else {
		coneScale = 1.f;
		dustParticles = 10;
	}
	
	cone1.Update(g_gameTime.lastFrameDuration(), m_pos, coneScale);
	cone2.Update(g_gameTime.lastFrameDuration(), m_pos, coneScale);
	
	m_stones.Update(g_gameTime.lastFrameDuration(), m_pos);
	
	for(int i = 0; i < dustParticles; i++) {
		createDustParticle();
	}
	
	cone1.Render();
	cone2.Render();
	m_stones.DrawStone();
	
	ARX_SOUND_RefreshPosition(m_snd_loop, entities[m_target]->pos);
}
Пример #10
0
void RotatingCone::Update(GameDuration timeDelta, Vec3f pos, float coneScale) {
	
	m_currdurationang += timeDelta;
	
	m_pos = pos;
	m_coneScale = coneScale;
	
	m_ang = m_currdurationang / GameDurationMs(1000);
	
	if(m_ang > 1.f) {
		m_currdurationang = 0;
		m_ang = 1.f;
	}
}
Пример #11
0
void CPoisonProjectile::Update(GameDuration timeDelta)
{
	if(m_elapsed <= GameDurationMs(2000)) {
		m_elapsed += timeDelta;
	}

	// on passe de 5 à 100 partoches en 1.5secs
	if(m_elapsed < GameDurationMs(750)) {
		pPS.m_parameters.m_nbMax = 2;
		pPS.Update(timeDelta);
	} else {
		if(!bOk) {
			bOk = true;
			// go
			
			ParticleParams pp = g_particleParameters[ParticleParam_Poison3];
			pp.m_pos = Vec3f(fBetaRadSin * 20, 0.f, fBetaRadCos * 20);
			pp.m_direction = -eMove * 0.1f;
			
			pPSStream.SetParams(pp);
		}

		pPSStream.Update(timeDelta);
		pPSStream.SetPos(eCurPos);

		pPS.Update(timeDelta);
		pPS.SetPos(eCurPos);

		fTrail = ((m_elapsed - GameDurationMs(750)) / (m_duration - GameDurationMs(750))) * 9 * (BEZIERPrecision + 2);
	}

	if(m_elapsed >= m_duration)
		lightIntensityFactor = 0.f;
	else
		lightIntensityFactor = 1.f;
}
Пример #12
0
void IncinerateSpell::Launch() {
	
	Entity * tio = entities[m_target];
	
	ARX_SOUND_PlaySFX(SND_SPELL_INCINERATE, &tio->pos);
	
	m_snd_loop = ARX_SOUND_PlaySFX(SND_SPELL_INCINERATE_LOOP, &tio->pos, 1.f, ARX_SOUND_PLAY_LOOPED);
	
	m_duration = GameDurationMs(20000);
	m_hasDuration = true;
	
	tio->sfx_flag |= SFX_TYPE_YLSIDE_DEATH | SFX_TYPE_INCINERATE;
	tio->sfx_time = g_gameTime.now();
	
	m_targets.push_back(m_target);
}
Пример #13
0
void MemorizedRunesHud::draw() {
	
	if(!(CurrSpellSymbol || player.SpellToMemorize.bSpell)) {
		return;
	}
	
	Vec2f pos = m_rect.topLeft();
	
	for(int i = 0; i < 6; i++) {
		bool bHalo = false;
		if(SpellSymbol[i] != RUNE_NONE) {
			if(SpellSymbol[i] == player.SpellToMemorize.iSpellSymbols[i]) {
				bHalo = true;
			} else {
				player.SpellToMemorize.iSpellSymbols[i] = SpellSymbol[i];
				for(int j = i + 1; j < 6; j++) {
					player.SpellToMemorize.iSpellSymbols[j] = RUNE_NONE;
				}
			}
		}
		if(player.SpellToMemorize.iSpellSymbols[i] != RUNE_NONE) {
			
			Vec2f size = Vec2f(32.f, 32.f) * m_scale;
			Rectf rect = Rectf(pos, size.x, size.y);
			
			TextureContainer * tc = gui::necklace.pTexTab[player.SpellToMemorize.iSpellSymbols[i]];
			
			if(bHalo) {
				ARX_INTERFACE_HALO_Render(Color3f(0.2f, 0.4f, 0.8f), HALO_ACTIVE, tc->getHalo(), pos, Vec2f(m_scale));
			}
			
			EERIEDrawBitmap(rect, 0, tc, Color::white);
			
			if(!player.hasRune(player.SpellToMemorize.iSpellSymbols[i])) {
				UseRenderState state(render2D().blend(BlendInvDstColor, BlendOne).alphaCutout());
				EERIEDrawBitmap(rect, 0, cursorMovable, Color3f::gray(.8f).to<u8>());
			}
			
			pos.x += 32 * m_scale;
		}
	}
	if(g_gameTime.now() - player.SpellToMemorize.lTimeCreation > GameDurationMs(30000)) {
		player.SpellToMemorize.bSpell = false;
	}
}
Пример #14
0
void PrecastSpellsGui::update() {
	m_icons.clear();
	
	if(!isVisible())
		return;
	
	float intensity = 1.f - PULSATE * 0.5f;
	intensity = glm::clamp(intensity, 0.f, 1.f);
	
	
	for(size_t i = 0; i < Precast.size(); i++) {
		
		PRECAST_STRUCT & precastSlot = Precast[i];
		
		float val = intensity;
		
		if(precastSlot.launch_time > 0 && g_gameTime.now() >= precastSlot.launch_time) {
			float tt = (g_gameTime.now() - precastSlot.launch_time) / GameDurationMs(1000);
			
			if(tt > 1.f)
				tt = 1.f;
			
			val *= (1.f - tt);
		}
		
		Color color = Color3f(0, val * 0.5f, val).to<u8>();
		
		Rectf childRect = createChild(m_rect, Anchor_BottomLeft, m_iconSize * m_scale, Anchor_BottomLeft);
		childRect.move(i * m_iconSize.x * m_scale, 0);
		
		SpellType typ = precastSlot.typ;
		
		TextureContainer * tc = spellicons[typ].tc;
		arx_assert(tc);
		
		PrecastSpellIconSlot icon;
		icon.update(childRect, tc, color, PrecastHandle(i));
		
		if(!(player.Interface & INTER_COMBATMODE))
			icon.updateInput();
		
		m_icons.push_back(icon);
	}
}
Пример #15
0
void CurseSpell::Update() {
	
	fRot += g_gameTime.lastFrameDuration() / GameDurationMs(4);
	
	Vec3f target = Vec3f_ZERO;
	
	Entity * targetIo = entities.get(m_target);
	if(targetIo) {
		target = targetIo->pos;

		if(m_target == EntityHandle_Player)
			target.y -= 200.f;
		else
			target.y += targetIo->physics.cyl.height - 30.f;
	}
	m_pos = target;
	
	RenderMaterial mat;
	mat.setCulling(CullCW);
	mat.setDepthTest(true);
	mat.setBlendType(RenderMaterial::Opaque);
	
	Draw3DObject(svoodoo, Anglef(0, fRot, 0), m_pos, Vec3f_ONE, Color3f::white, mat);
	
	for(int i = 0; i < 4; i++) {
		
		PARTICLE_DEF * pd = createParticle();
		if(!pd) {
			break;
		}
		
		pd->ov = m_pos;
		pd->move = arx::linearRand(Vec3f(-2.f, -20.f, -2.f), Vec3f(2.f, -10.f, 2.f));
		pd->siz = 0.015f;
		pd->tolive = Random::getu(1000, 1600);
		pd->tc = tex_p1;
		pd->m_flags = ROTATING | DISSIPATING | SUBSTRACT | GRAVITY;
		pd->m_rotation = 0.0000001f;
	}
}
Пример #16
0
void RuneOfGuardingSpell::Launch() {
	
	spells.endByCaster(m_caster, SPELL_RUNE_OF_GUARDING);
	
	ARX_SOUND_PlaySFX(g_snd.SPELL_RUNE_OF_GUARDING);
	
	m_hasDuration = m_launchDuration >= 0;
	m_duration = m_hasDuration ? m_launchDuration : 0;
	
	m_pos = entities[m_caster]->pos;
	
	tex_p2 = TextureContainer::Load("graph/obj3d/textures/(fx)_tsu_blueting");
	
	EERIE_LIGHT * light = dynLightCreate(m_light);
	if(light) {
		light->intensity = 0.7f + 2.3f;
		light->fallend = 500.f;
		light->fallstart = 400.f;
		light->rgb = Color3f(1.0f, 0.2f, 0.2f);
		light->pos = m_pos - Vec3f(0.f, 50.f, 0.f);
		light->creationTime = g_gameTime.now();
		light->duration = GameDurationMs(200);
	}
}
Пример #17
0
void ConfuseSpell::End() {
	
	m_targets.clear();
	endLightDelayed(m_light, GameDurationMs(500));
}
Пример #18
0
void IceFieldSpell::Update() {
	
	EERIE_LIGHT * el = dynLightCreate(m_light);
	if(el) {
		el->pos = m_pos + Vec3f(0.f, -120.f, 0.f);
		el->intensity = 4.6f;
		el->fallstart = Random::getf(150.f, 180.f);
		el->fallend   = Random::getf(290.f, 320.f);
		el->rgb = Color3f(0.76f, 0.76f, 1.0f) + Color3f(0.f, 0.f, Random::getf(-0.1f, 0.f));
		el->duration = GameDurationMs(600);
		el->extras = 0;
	}

	if(!VisibleSphere(Sphere(m_pos - Vec3f(0.f, 120.f, 0.f), 350.f))) {
		return;
	}
	
	RenderMaterial mat;
	mat.setDepthTest(true);
	mat.setBlendType(RenderMaterial::Additive);
	
	for(int i = 0; i < iMax; i++) {
		
		tSize[i] += Vec3f(0.1f);
		tSize[i] = glm::min(tSize[i], tSizeMax[i]);
		
		Anglef stiteangle(0.f, glm::cos(glm::radians(tPos[i].x)) * 360, 0.f);
		Vec3f stitepos(tPos[i].x, m_pos.y, tPos[i].z);
		Vec3f stitescale(tSize[i].z, tSize[i].y, tSize[i].x);
		Color3f stitecolor = Color3f(0.7f, 0.7f, 0.9f) * tSizeMax[i].y;
		
		if(stitecolor.r > 1) {
			stitecolor.r = 1;
		}
		
		if(stitecolor.g > 1) {
			stitecolor.g = 1;
		}
		
		if(stitecolor.b > 1) {
			stitecolor.b = 1;
		}
		
		EERIE_3DOBJ * obj = (tType[i] == 0) ? smotte : stite;
		
		Draw3DObject(obj, stiteangle, stitepos, stitescale, stitecolor, mat);
	}
	
	for(int i = 0; i < iMax * 0.5f; i++) {
		
		float t = Random::getf();
		if(t < 0.01f) {
			
			PARTICLE_DEF * pd = createParticle();
			if(pd) {
				pd->ov = tPos[i] + arx::randomVec(-5.f, 5.f);
				pd->move = arx::randomVec(-2.f, 2.f);
				pd->siz = 20.f;
				pd->tolive = Random::getu(2000, 6000);
				pd->tc = tex_p2;
				pd->m_flags = FADE_IN_AND_OUT | ROTATING | DISSIPATING;
				pd->m_rotation = 0.0000001f;
				pd->rgb = Color3f(0.7f, 0.7f, 1.f);
			}
			
		} else if(t > 0.095f) {
			
			PARTICLE_DEF * pd = createParticle();
			if(pd) {
				pd->ov = tPos[i] + arx::randomVec(-5.f, 5.f) + Vec3f(0.f, 50.f, 0.f);
				pd->move = Vec3f(0.f, Random::getf(-2.f, 2.f), 0.f);
				pd->siz = 0.5f;
				pd->tolive = Random::getu(2000, 6000);
				pd->tc = tex_p1;
				pd->m_flags = FADE_IN_AND_OUT | ROTATING | DISSIPATING;
				pd->m_rotation = 0.0000001f;
				pd->rgb = Color3f(0.7f, 0.7f, 1.f);
			}
			
		}
		
	}
	
}
Пример #19
0
void IceFieldSpell::Launch() {
	
	spells.endByCaster(m_caster, SPELL_ICE_FIELD);
	
	ARX_SOUND_PlaySFX(g_snd.SPELL_ICE_FIELD);
	
	m_duration = (m_launchDuration >= 0) ? m_launchDuration : GameDurationMs(100000);
	m_hasDuration = true;
	m_fManaCostPerSecond = 2.8f;
	m_light = LightHandle();
	
	Vec3f target;
	float beta;
	bool displace;
	if(m_caster == EntityHandle_Player) {
		target = player.basePosition();
		beta = player.angle.getYaw();
		displace = true;
	} else {
		Entity * io = entities.get(m_caster);
		arx_assert(io);
		target = io->pos;
		beta = io->angle.getYaw();
		displace = (io->ioflags & IO_NPC) == IO_NPC;
	}
	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 = GameDurationMs(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 = Random::getf();

		if(t < 0.5f) {
			tType[i] = 0;
		} else {
			tType[i] = 1;
		}
		
		tSize[i] = Vec3f(0.f);
		tSizeMax[i] = arx::randomVec3f() + Vec3f(0.f, 0.2f, 0.f);
		
		Vec3f minPos = (tType[i] == 0) ? Vec3f(1.2f, 1.f, 1.2f) : Vec3f(0.4f, 0.3f, 0.4f);
		
		tSizeMax[i] = glm::max(tSizeMax[i], minPos);
		
		if(tType[i] == 0) {
			tPos[i].x = m_pos.x + Random::getf(-80.f, 80.f);
			tPos[i].y = m_pos.y;
			tPos[i].z = m_pos.z + Random::getf(-80.f, 80.f);
		} else {
			tPos[i].x = m_pos.x + Random::getf(-120.f, 120.f);
			tPos[i].y = m_pos.y;
			tPos[i].z = m_pos.z + Random::getf(-120.f, 120.f);
		}
	}
	
	m_snd_loop = ARX_SOUND_PlaySFX_loop(g_snd.SPELL_ICE_FIELD_LOOP, &target, 1.f);
}
Пример #20
0
QuickSaveIconGui::QuickSaveIconGui()
	: m_duration(GameDurationMs(1000))
	, m_remainingTime(0)
{}
Пример #21
0
void BlessSpell::Update() {
	
	fRot += g_gameTime.lastFrameDuration() / GameDurationMs(4);
	
	Entity * target = entities.get(m_target);
	if(target) {
		m_pos = target->pos;
		
		if(m_target == EntityHandle_Player)
			m_yaw = player.angle.getYaw();
		else
			m_yaw = target->angle.getYaw();
	}
	
	m_scale = (m_level + 10) * 6.f;
	
	Vec3f pos = m_pos + Vec3f(0, -5, 0);
	
	RenderMaterial mat;
	mat.setCulling(CullNone);
	mat.setBlendType(RenderMaterial::Additive);
	mat.setDepthTest(true);
	mat.setLayer(RenderMaterial::Decal);
	mat.setTexture(tex_sol);
	
	float fBetaRadCos = glm::cos(glm::radians(MAKEANGLE(m_yaw))) * m_scale;
	float fBetaRadSin = glm::sin(glm::radians(MAKEANGLE(m_yaw))) * m_scale;

	ColorRGBA color = Color::white.toRGB();
	
	{
	TexturedQuad q;
	
	q.v[0].color = color;
	q.v[1].color = color;
	q.v[2].color = color;
	q.v[3].color = color;
	
	q.v[0].uv = Vec2f_ZERO;
	q.v[1].uv = Vec2f_X_AXIS;
	q.v[2].uv = Vec2f_ONE;
	q.v[3].uv = Vec2f_Y_AXIS;
	
	q.v[0].p.x = pos.x + fBetaRadCos - fBetaRadSin;
	q.v[0].p.y = pos.y;
	q.v[0].p.z = pos.z + fBetaRadSin + fBetaRadCos;
	q.v[1].p.x = pos.x - fBetaRadCos - fBetaRadSin;
	q.v[1].p.y = pos.y;
	q.v[1].p.z = pos.z - fBetaRadSin + fBetaRadCos;
	q.v[2].p.x = pos.x - fBetaRadCos + fBetaRadSin;
	q.v[2].p.y = pos.y;
	q.v[2].p.z = pos.z - fBetaRadSin - fBetaRadCos;
	q.v[3].p.x = pos.x + fBetaRadCos + fBetaRadSin;
	q.v[3].p.y = pos.y;
	q.v[3].p.z = pos.z + fBetaRadSin - fBetaRadCos;
	
	drawQuadRTP(mat, q);
	}
	
	for(int i = 0; i < 12; i++) {
		
		PARTICLE_DEF * pd = createParticle();
		if(!pd) {
			break;
		}
		
		pd->ov = m_pos - Vec3f(0.f, 20.f, 0.f);
		pd->move = arx::linearRand(Vec3f(-3.f, 0.f, -3.f), Vec3f(3.f, 0.5f, 3.f));
		pd->siz = 0.005f;
		pd->tolive = Random::getu(1000, 2000);
		pd->tc = tex_p1;
		pd->m_flags = FADE_IN_AND_OUT | ROTATING | DISSIPATING;
		pd->m_rotation = 0.0000001f;
		pd->rgb = Color3f(0.7f, 0.6f, 0.2f);
	}
}
Пример #22
0
void RuneOfGuardingSpell::End() {
	
	endLightDelayed(m_light, GameDurationMs(500));
}
Пример #23
0
void DispellFieldSpell::Launch() {
	
	m_duration = GameDurationMs(10);
	m_hasDuration = true;
	
	long valid = 0, dispelled = 0;

	for(size_t n = 0; n < MAX_SPELLS; n++) {
		SpellBase * spell = spells[SpellHandle(n)];
		
		if(!spell) {
			continue;
		}
		
		bool cancel = false;
		Vec3f pos;
		
		switch(spell->m_type) {
			
			case SPELL_CREATE_FIELD: {
				if(m_caster != EntityHandle_Player || spell->m_caster == EntityHandle_Player) {
					pos = static_cast<CreateFieldSpell *>(spell)->getPosition();
					cancel = true;
				}
				break;
			}
			
			case SPELL_FIRE_FIELD: {
				pos = static_cast<FireFieldSpell *>(spell)->getPosition();
				cancel = true;
				break;
			}
			
			case SPELL_ICE_FIELD: {
				pos = static_cast<IceFieldSpell *>(spell)->getPosition();
				cancel = true;
				break;
			}
			
			default: break;
		}
		
		Entity * caster = entities[m_caster];
		if(cancel && closerThan(pos, caster->pos, 400.f)) {
			valid++;
			if(spell->m_level <= m_level) {
				spells.endSpell(spell);
				dispelled++;
			}
		}
	}
	
	if(valid > dispelled) {
		// Some fileds could not be dispelled
		ARX_SPEECH_AddSpeech(entities.player(), "player_not_skilled_enough",
		                     ANIM_TALK_NEUTRAL, ARX_SPEECH_FLAG_NOTEXT);
	}
	
	if(dispelled > 0) {
		ARX_SOUND_PlaySFX(SND_SPELL_DISPELL_FIELD);
	} else {
		ARX_SOUND_PlaySFX(SND_MAGIC_FIZZLE, &m_caster_pos);
	}
}
Пример #24
0
void SummonCreatureSpell::Update() {
	
	if(g_gameTime.isPaused()) {
		return;
	}
	
	if(m_elapsed <= GameDurationMs(4000)) {
		if(Random::getf() > 0.7f) {
			Vec3f pos = m_fissure.m_eSrc;
			MakeCoolFx(pos);
		}
		
		m_fissure.Update(g_gameTime.lastFrameDuration());
		m_fissure.Render();
		
		m_requestSummon = true;
		m_summonedEntity = EntityHandle();

	} else if(m_requestSummon) {
		lightHandleDestroy(m_light);
		
		m_requestSummon = false;
		ARX_SOUND_PlaySFX(SND_SPELL_ELECTRIC, &m_targetPos);
		
		Cylinder phys = Cylinder(m_targetPos, 50, -200);
		
		float anything = CheckAnythingInCylinder(phys, NULL, CFLAG_JUST_TEST);
		
		if(glm::abs(anything) < 30) {
			
			long tokeep;
			res::path cls;
			if(m_megaCheat) {
				if(Random::getf() > 0.5f) {
					tokeep = -1;
					cls = "graph/obj3d/interactive/npc/wrat_base/wrat_base";
				} else {
					tokeep = 0;
					cls = "graph/obj3d/interactive/npc/y_mx/y_mx";
				}
			} else if(Random::getf() > 0.997f || (sp_max && Random::getf() > 0.8f)
			   || (cur_mr >= 3 && Random::getf() > 0.3f)) {
				tokeep = 0;
				cls = "graph/obj3d/interactive/npc/y_mx/y_mx";
			} else if(Random::getf() > 0.997f || (cur_rf >= 3 && Random::getf() > 0.8f)
			   || (cur_mr >= 3 && Random::getf() > 0.3f)) {
				tokeep = -1;
				cls = "graph/obj3d/interactive/npc/wrat_base/wrat_base";
			} else if(m_level >= 9) {
				tokeep = 1;
				cls = "graph/obj3d/interactive/npc/demon/demon";
			} else if(Random::getf() > 0.98f) {
				tokeep = -1;
				cls = "graph/obj3d/interactive/npc/wrat_base/wrat_base";
			} else {
				tokeep = 0;
				cls = "graph/obj3d/interactive/npc/chicken_base/chicken_base";
			}
			
			Entity * io = AddNPC(cls, -1, IO_IMMEDIATELOAD);
			if(!io) {
				cls = "graph/obj3d/interactive/npc/chicken_base/chicken_base";
				tokeep = 0;
				io = AddNPC(cls, -1, IO_IMMEDIATELOAD);
			}
			
			if(io) {
				RestoreInitialIOStatusOfIO(io);
				
				io->summoner = m_caster;
				
				io->scriptload = 1;
				
				if(tokeep == 1) {
					io->ioflags |= IO_NOSAVE;
				}
				
				io->pos = phys.origin;
				SendInitScriptEvent(io);
				
				if(tokeep < 0) {
					io->scale = 1.65f;
					io->physics.cyl.radius = 25;
					io->physics.cyl.height = -43;
					io->speed_modif = 1.f;
				}
				
				SendIOScriptEvent(entities.get(m_caster), io, SM_SUMMONED);
				
				for(long j = 0; j < 3; j++) {
					Vec3f pos = m_fissure.m_eSrc;
					pos += arx::randomVec3f() * 100.f;
					pos += Vec3f(-50.f, 50.f, -50.f);
					
					MakeCoolFx(pos);
				}
				
				if(tokeep == 1) {
					m_summonedEntity = io->index();
				} else {
					m_summonedEntity = EntityHandle();
				}
				
			}
		}
		
	} else if(m_summonedEntity == EntityHandle()) {
		requestEnd();
	}
	
}
Пример #25
0
void RepelUndeadSpell::Update() {
	
	Vec3f pos = entities[m_target]->pos;
	
	float rot;
	if(m_target == EntityHandle_Player) {
		rot = player.angle.getYaw();
	} else {
		rot = entities[m_target]->angle.getYaw();
	}
	
	m_pos = pos;
	m_yaw = rot;
	
	RenderMaterial mat;
	mat.setDepthTest(true);
	mat.setBlendType(RenderMaterial::Additive);
	
	Anglef  eObjAngle;

	eObjAngle.setYaw(m_yaw);
	eObjAngle.setPitch(0);
	eObjAngle.setRoll(0);
	
	float wave = timeWaveSin(g_gameTime.now(), GameDurationMsf(6283.185307f));
	
	float vv = (1.f + wave) * 0.5f + 1.1f;
	
	Draw3DObject(ssol, eObjAngle, m_pos + Vec3f(0.f, -5.f, 0.f), Vec3f(vv), Color3f(0.6f, 0.6f, 0.8f), mat);
	
	vv *= 100.f;
	
	for(int n = 0; n < 4; n++) {
		
		PARTICLE_DEF * pd = createParticle();
		if(!pd) {
			break;
		}
		
		// XXX was this supposed to be sphericalRand ?
		Vec2f d = arx::diskRand(vv);
		
		pd->ov = m_pos + Vec3f(d.x, 0.f, d.y);
		pd->move = arx::linearRand(Vec3f(-0.8f, -4.f, -0.8f), Vec3f(0.8f, 0.f, 0.8f));
		pd->scale = Vec3f(-0.1f);
		pd->tolive = Random::getu(2600, 3200);
		pd->tc = tex_p2;
		pd->siz = 0.3f;
		pd->rgb = Color3f(.4f, .4f, .6f);
	}
	
	EERIE_LIGHT * light = dynLightCreate(m_light);
	if(light) {
		light->intensity = 2.3f;
		light->fallend = 350.f;
		light->fallstart = 150.f;
		light->rgb = Color3f(0.8f, 0.8f, 1.f);
		light->pos = m_pos + Vec3f(0.f, -50.f, 0.f);
		light->duration = GameDurationMs(200);
		light->creationTime = g_gameTime.now();
	}
	
	if (m_target == EntityHandle_Player)
		ARX_SOUND_RefreshPosition(m_snd_loop, entities[m_target]->pos);
}
Пример #26
0
void ConfuseSpell::Update() {
	
	Entity * target = entities.get(m_target);
	if(!target) {
		return;
	}
	
	Vec3f pos = target->pos;
	if(m_target != EntityHandle_Player) {
		pos.y += target->physics.cyl.height - 30.f;
	}
	
	ObjVertHandle idx = target->obj->fastaccess.head_group_origin;
	if(idx != ObjVertHandle()) {
		pos = target->obj->vertexWorldPositions[idx.handleData()].v;
		pos.y -= 50.f;
	}
	
	eCurPos = pos;
	
	RenderMaterial mat;
	mat.setDepthTest(false);
	mat.setBlendType(RenderMaterial::Additive);
	mat.setTexture(tex_trail);
	
	float rot = timeWaveSaw(g_gameTime.now(), GameDurationMs(3142)) * 360.f;
	
	Anglef stiteangle = Anglef(0.f, -rot, 0.f);
	
	{
		AnimationDuration delta = toAnimationDuration(g_gameTime.lastFrameDuration());
		EERIEDrawAnimQuatUpdate(spapi, animlayer, stiteangle, eCurPos, delta, NULL, false);
		EERIEDrawAnimQuatRender(spapi, eCurPos, NULL, 0.f);
	}
	
	for(int i = 0; i < 6; i++) {
		
		PARTICLE_DEF * pd = createParticle();
		if(!pd) {
			break;
		}
		
		Vec2f p = arx::diskRand(15.f);
		pd->ov = eCurPos + Vec3f(p.x, 0.f, p.y);
		
		pd->move = Vec3f(0.f, Random::getf(1.f, 4.f), 0.f);
		pd->siz = 0.25f;
		pd->tolive = Random::getu(2300, 3300);
		pd->tc = tex_p1;
		pd->m_flags = PARTICLE_GOLDRAIN | FADE_IN_AND_OUT | ROTATING | DISSIPATING;
		pd->m_rotation = 0.0000001f;
		
		Color3f baseColor = Color3f(0.4f, 0.2f, 0.4f);
		Color3f randomFactor = Color3f(0.4f, 0.6f, 0.4f);
		Color3f c = baseColor + randomColor3f() * randomFactor;
		while(glm::abs(c.r - c.g) > 0.3f && glm::abs(c.g - c.b) > 0.3f) {
			c = baseColor + randomColor3f() * randomFactor;
		}
		pd->rgb = c * Color3f(0.8f, 0.8f, 0.8f);
	}
	
	EERIE_LIGHT * light = dynLightCreate(m_light);
	if(light) {
		light->intensity = 1.3f;
		light->fallstart = 180.f;
		light->fallend   = 420.f;
		light->rgb = Color3f(0.3f, 0.3f, 0.5f) + Color3f(0.2f, 0.f, 0.2f) * randomColor3f();
		light->pos = eCurPos;
		light->duration = GameDurationMs(200);
		light->extras = 0;
	}
}
Пример #27
0
void RuneOfGuardingSpell::Update() {
	
	EERIE_LIGHT * light = lightHandleGet(m_light);
	if(light) {
		float fa = Random::getf(0.85f, 1.0f);
		light->intensity = 0.7f + 2.3f * fa;
		light->fallend = 350.f;
		light->fallstart = 150.f;
		light->rgb = Color3f(1.0f, 0.2f, 0.2f);
		light->creationTime = g_gameTime.now();
		light->duration = GameDurationMs(200);
	}
	
	Vec3f pos = m_pos + Vec3f(0.f, -20.f, 0.f);
	
	RenderMaterial mat;
	mat.setDepthTest(true);
	mat.setBlendType(RenderMaterial::Additive);
	
	Anglef stiteangle;
	Color3f stitecolor;
	
	float stiteangleb = m_elapsed / GameDurationMs(100);
	stiteangle.setPitch(0);
	stiteangle.setRoll(0);
	
	stiteangle.setYaw(stiteangleb * 0.1f);
	stitecolor = Color3f(0.4f, 0.4f, 0.6f);
	float scale = std::sin(m_elapsed / GameDurationMsf(66.6666666f));
	Vec3f stitescale = Vec3f(1.f, -0.1f, 1.f);
	
	Draw3DObject(slight, stiteangle, pos, stitescale, stitecolor, mat);
	
	stiteangle.setYaw(stiteangleb);
	stitecolor = Color3f(0.6f, 0.f, 0.f);
	stitescale = Vec3f(2.f) * (1.f + 0.01f * scale);
	
	Draw3DObject(ssol, stiteangle, pos, stitescale, stitecolor, mat);
	
	stitecolor = Color3f(0.6f, 0.3f, 0.45f);
	stitescale = Vec3f(1.8f) * (1.f + 0.02f * scale);
	
	Draw3DObject(srune, stiteangle, pos, stitescale, stitecolor, mat);
	
	for(int n = 0; n < 4; n++) {
		
		PARTICLE_DEF * pd = createParticle();
		if(!pd) {
			break;
		}
		
		pd->ov = pos + arx::randomOffsetXZ(40.f);
		pd->move = arx::linearRand(Vec3f(-0.8f, -4.f, -0.8f), Vec3f(0.8f, 0.f, 0.8f));
		pd->scale = Vec3f(-0.1f);
		pd->tolive = Random::getu(2600, 3200);
		pd->tc = tex_p2;
		pd->siz = 0.3f;
		pd->rgb = Color3f(.4f, .4f, .6f);
	}
	
	
	
	Sphere sphere = Sphere(m_pos, std::max(m_level * 15.f, 50.f));
	if(CheckAnythingInSphere(sphere, m_caster, CAS_NO_SAME_GROUP | CAS_NO_BACKGROUND_COL | CAS_NO_ITEM_COL
	                                           | CAS_NO_FIX_COL | CAS_NO_DEAD_COL)) {
		spawnFireHitParticle(m_pos, 0);
		PolyBoomAddScorch(m_pos);
		LaunchFireballBoom(m_pos, m_level);
		DoSphericDamage(Sphere(m_pos, 30.f * m_level), 4.f * m_level,
		                DAMAGE_AREA, DAMAGE_TYPE_FIRE | DAMAGE_TYPE_MAGICAL, m_caster);
		ARX_SOUND_PlaySFX(g_snd.SPELL_RUNE_OF_GUARDING_END, &m_pos);
		requestEnd();
	}
}
Пример #28
0
void CCreateField::Render()
{
	if(!VisibleSphere(Sphere(eSrc - Vec3f(0.f, 120.f, 0.f), 400.f)))
		return;
	
	//-------------------------------------------------------------------------
	// rendu
	if(youp) {
		fglow += 0.5f;

		if(fglow >= 50) {
			youp = false;
		}
	} else {
		fglow -= 0.5f;

		if(fglow <= 0) {
			youp = true;
		}
	}
	
	float ysize = std::min(1.0f, m_elapsed / GameDurationMs(1000));
	
	if(ysize >= 1.0f) {
		size = std::min(1.0f, (m_elapsed - GameDurationMs(1000)) / GameDurationMs(1000));
		size = std::max(size, 0.1f);
	}

	// ondulation
	ft += 0.01f;

	if(ft > 360.0f) {
		ft = 0.0f;
	}

	falpha = glm::sin(glm::radians(fglow)) + Random::getf(0.f, 0.2f);
	falpha = glm::clamp(falpha, 0.f, 1.f);
	
	float smul = 100 * size;

	// bottom points
	Vec3f b[4] = {
		eSrc + Vec3f(-smul, 0.f, -smul),
		eSrc + Vec3f(smul, 0.f, -smul),
		eSrc + Vec3f(smul, 0.f, smul),
		eSrc + Vec3f(-smul, 0.f, smul)
	};
	
	// top points
	Vec3f t[4] = {
		b[0] + Vec3f(0.f, -250 * ysize, 0.f),
		b[1] + Vec3f(0.f, -250 * ysize, 0.f),
		b[2] + Vec3f(0.f, -250 * ysize, 0.f),
		b[3] + Vec3f(0.f, -250 * ysize, 0.f)
	};
	
	fwrap -= 5.0f; // TODO ignores the frame delay
	while(fwrap < 0) {
		fwrap += 360;
	}
	
	RenderMaterial mat;
	mat.setTexture(tex_jelly);
	mat.setDepthTest(true);
	mat.setBlendType(RenderMaterial::Additive);
	
	RenderSubDivFace(b, b, 0, 1, 2, 3, mat);
	RenderSubDivFace(t, t, 0, 3, 2, 1, mat);
	RenderSubDivFace(b, t, 1, 0, 0, 1, mat);
	RenderSubDivFace(b, t, 3, 2, 2, 3, mat);
	RenderSubDivFace(b, t, 0, 3, 3, 0, mat);
	RenderSubDivFace(b, t, 2, 1, 1, 2, mat);
	
	EERIE_LIGHT * light = lightHandleGet(lLightId);
	if(light) {
		light->intensity = 0.7f + 2.3f * falpha;
		light->fallend = 500.f;
		light->fallstart = 400.f;
		light->rgb = Color3f(0.8f, 0.0f, 1.0f);
		light->pos = eSrc + Vec3f(0.f, -150.f, 0.f);
		light->duration = GameDurationMs(800);
	}
	
}
Пример #29
0
void TreatBackgroundDynlights() {
	
	ARX_PROFILE_FUNC();
	
	for(size_t i = 0; i < g_staticLightsMax; i++) {
		EERIE_LIGHT * light = g_staticLights[i];
		
		if(light && (light->extras & EXTRAS_SEMIDYNAMIC)) {
			
			float fMaxdist = player.m_telekinesis ? 850 : 300;
			
			if(!fartherThan(light->pos, g_camera->m_pos, fMaxdist)) {
				ComputeLight2DPos(light);
			} else {
				light->m_screenRect = Rectf(1, 0, -1, 0); // Intentionally invalid
			}
			
			if(!light->m_ignitionStatus) {
				
				// just extinguished
				EERIE_LIGHT * dynLight = lightHandleGet(light->m_ignitionLightHandle);
				if(dynLight) {
					dynLight->m_exists = false;
					light->m_ignitionLightHandle = LightHandle();
					for(size_t l = 0; l < entities.size(); l++) {
						const EntityHandle handle = EntityHandle(l);
						Entity * e = entities[handle];
						if(e && (e->ioflags & IO_MARKER)) {
							Vec3f _pos2 = GetItemWorldPosition(e);
							if(!fartherThan(light->pos, _pos2, 300.f)) {
								SendIOScriptEvent(NULL, e, SM_CUSTOM, "douse");
							}
						}
					}
				}
				
			} else {
				
				// just light up
				if(!lightHandleGet(light->m_ignitionLightHandle)) {
					for(size_t l = 0; l < entities.size(); l++) {
						const EntityHandle handle = EntityHandle(l);
						Entity * e = entities[handle];
						if(e && (e->ioflags & IO_MARKER)) {
							Vec3f _pos2 = GetItemWorldPosition(e);
							if(!fartherThan(light->pos, _pos2, 300.f)) {
								SendIOScriptEvent(NULL, e, SM_CUSTOM, "fire");
							}
						}
					}
					light->m_ignitionLightHandle = GetFreeDynLight();
				}
				
				EERIE_LIGHT * dynamicLight = lightHandleGet(light->m_ignitionLightHandle);
				if(dynamicLight) {
					dynamicLight->pos          = light->pos;
					dynamicLight->fallstart    = light->fallstart;
					dynamicLight->fallend      = light->fallend;
					dynamicLight->m_isIgnitionLight  = true;
					dynamicLight->intensity    = light->intensity;
					dynamicLight->ex_flaresize = light->ex_flaresize;
					dynamicLight->extras       = light->extras;
					dynamicLight->duration     = GameDurationMs(std::numeric_limits<long>::max());
					
					dynamicLight->rgb = light->rgb - light->rgb * light->ex_flicker * randomColor3f() * 0.5f;
					
					dynamicLight->rgb = componentwise_max(dynamicLight->rgb, Color3f::black);
					RecalcLight(dynamicLight);
				}
			}
		}
	}

	for(size_t i = 0; i < g_dynamicLightsMax; i++) {
		EERIE_LIGHT * el = &g_dynamicLights[i];

		if(el->m_exists && el->duration != 0) {
			const GameDuration elapsed = g_gameTime.now() - el->creationTime;
			const GameDuration duration = el->duration;

			if(elapsed >= duration) {
				float sub = g_gameTime.lastFrameDuration() / GameDurationMs(1000);

				el->rgb.r -= sub;
				el->rgb.g -= sub;
				el->rgb.b -= sub;

				if(el->rgb.r < 0)
					el->rgb.r = 0.f;

				if(el->rgb.g < 0)
					el->rgb.g = 0.f;

				if(el->rgb.b < 0)
					el->rgb.b = 0.f;

				if(el->rgb.r + el->rgb.g + el->rgb.b == 0) {
					el->m_exists = false;
					el->duration = 0;
				}
			}
		}
	}
}
Пример #30
0
void PoisonProjectileSpell::Launch() {
	
	ARX_SOUND_PlaySFX(g_snd.SPELL_POISON_PROJECTILE_LAUNCH,
	                  &m_caster_pos);
	
	Vec3f srcPos(0.f);
	float afBeta = 0.f;
	
	Entity * caster = entities[m_caster];
	m_hand_group = caster->obj->fastaccess.primary_attach;

	if(m_hand_group != ActionPoint()) {
		ActionPoint group = m_hand_group;
		m_hand_pos = actionPointPosition(caster->obj, group);
	}
	
	if(m_caster == EntityHandle_Player) {

		afBeta = player.angle.getYaw();

		if(m_hand_group != ActionPoint()) {
			srcPos = m_hand_pos;
		} else {
			srcPos = player.pos;
		}
	} else {
		afBeta = entities[m_caster]->angle.getYaw();

		if(m_hand_group != ActionPoint()) {
			srcPos = m_hand_pos;
		} else {
			srcPos = entities[m_caster]->pos;
		}
	}
	
	srcPos += angleToVectorXZ(afBeta) * 90.f;
	
	size_t uiNumber = glm::clamp(static_cast<unsigned int>(m_level), 1u, 5u);
	
	for(size_t i = 0; i < uiNumber; i++) {
		CPoisonProjectile * projectile = new CPoisonProjectile();
		
		m_projectiles.push_back(projectile);
	}
	
	m_duration = GameDurationMs(8000);
	m_hasDuration = true;
	
	GameDuration lMax = 0;
	
	for(size_t i = 0; i < m_projectiles.size(); i++) {
		CPoisonProjectile * projectile = m_projectiles[i];
		
		projectile->Create(srcPos, afBeta + Random::getf(-10.f, 10.f));
		GameDuration lTime = m_duration + GameDurationMs(Random::getu(0, 5000));
		projectile->SetDuration(lTime);
		lMax = std::max(lMax, lTime);
		
		EERIE_LIGHT * light = dynLightCreate(projectile->lLightId);
		if(light) {
			light->intensity = 2.3f;
			light->fallend = 250.f;
			light->fallstart = 150.f;
			light->rgb = Color3f::green;
			light->pos = projectile->eSrc;
			light->creationTime = g_gameTime.now();
			light->duration = GameDurationMs(200);
		}
	}
	
	m_duration = lMax + GameDurationMs(1000);
}