예제 #1
0
void ARX_PARTICLES_Update(EERIE_CAMERA * cam)  {
	
	ARX_PROFILE_FUNC();
	
	if(!ACTIVEBKG) {
		return;
	}
	
	if(ParticleCount == 0) {
		return;
	}
	
	const ArxInstant now = arxtime.now();
	
	long pcc = ParticleCount;
	
	for(size_t i = 0; i < MAX_PARTICLES && pcc > 0; i++) {

		PARTICLE_DEF * part = &particle[i];
		if(!part->exist) {
			continue;
		}

		long framediff = part->timcreation + part->tolive - now;
		long framediff2 = now - part->timcreation;
		
		if(framediff2 < long(part->delay)) {
			continue;
		}
		
		if(part->delay > 0) {
			part->timcreation += part->delay;
			part->delay=0;
			if((part->m_flags & DELAY_FOLLOW_SOURCE) && part->sourceionum != EntityHandle()
					&& entities[part->sourceionum]) {
				part->ov = *part->source;
				Entity * target = entities[part->sourceionum];
				Vec3f vector = (part->ov - target->pos) * Vec3f(1.f, 0.5f, 1.f);
				vector = glm::normalize(vector);
				part->move = vector * Vec3f(18.f, 5.f, 18.f) + randomVec(-0.5f, 0.5f);
				
			}
			continue;
		}
		
		if(!part->is2D) {

			EERIE_BKG_INFO * bkgData = getFastBackgroundData(part->ov.x, part->ov.z);

			if(!bkgData || !bkgData->treat) {
				part->exist = false;
				ParticleCount--;
				continue;
			}
		}
		
		if(framediff <= 0) {
			if((part->m_flags & FIRE_TO_SMOKE) && Random::getf() > 0.7f) {
				
				part->ov += part->move;
				part->tolive = part->tolive * 1.375f;
				part->m_flags &= ~FIRE_TO_SMOKE;
				part->tc = smokeparticle;
				part->scale = glm::abs(part->scale * 2.4f);
				part->rgb = Color3f::gray(.45f);
				part->move *= 0.5f;
				part->siz *= 1.f / 3;
				part->timcreation = now;
				
				framediff = part->tolive;
				
			} else {
				part->exist = false;
				ParticleCount--;
				continue;
			}
		}
		
		float val = (part->tolive - framediff) * 0.01f;
		
		Vec3f in = part->ov + part->move * val;
		Vec3f inn = in;
		
		if(part->m_flags & GRAVITY) {
			in.y = inn.y = inn.y + 1.47f * val * val;
		}
		
		float fd = float(framediff2) / float(part->tolive);
		float r = 1.f - fd;
		if(part->m_flags & FADE_IN_AND_OUT) {
			long t = part->tolive / 2;
			if(framediff2 <= t) {
				r = float(framediff2) / float(t);
			} else {
				r = 1.f - float(framediff2 - t) / float(t);
			}
		}
		
		if(!part->is2D) {
			
			Sphere sp;
			sp.origin = in;
			
			TexturedVertex out;
			EE_RTP(inn, out);
			
			if(out.rhw < 0 || out.p.z > cam->cdepth * fZFogEnd) {
				continue;
			}
			
			if(part->m_flags & SPLAT_GROUND) {
				float siz = part->siz + part->scale.x * fd;
				sp.radius = siz * 10.f;
				if(CheckAnythingInSphere(sp, EntityHandle_Player, CAS_NO_NPC_COL)) {
					if(Random::getf() < 0.9f) {
						Color3f rgb = part->rgb;
						PolyBoomAddSplat(sp, rgb, 0);
					}
					part->exist = false;
					ParticleCount--;
					continue;
				}
			}
			
			if(part->m_flags & SPLAT_WATER) {
				float siz = part->siz + part->scale.x * fd;
				sp.radius = siz * Random::getf(10.f, 30.f);
				if(CheckAnythingInSphere(sp, EntityHandle_Player, CAS_NO_NPC_COL)) {
					if(Random::getf() < 0.9f) {
						Color3f rgb = part->rgb * 0.5f;
						PolyBoomAddSplat(sp, rgb, 2);
					}
					part->exist = false;
					ParticleCount--;
					continue;
				}
			}
			
			if((part->m_flags & DISSIPATING) && out.p.z < 0.05f) {
				out.p.z *= 20.f;
				r *= out.p.z;
			}
		}
		
		if(r <= 0.f) {
			pcc--;
			continue;
		}
		
		if(part->m_flags & PARTICLE_GOLDRAIN) {
			float v = Random::getf(-0.1f, 0.1f);
			if(part->rgb.r + v <= 1.f && part->rgb.r + v > 0.f
				&& part->rgb.g + v <= 1.f && part->rgb.g + v > 0.f
				&& part->rgb.b + v <= 1.f && part->rgb.b + v > 0.f) {
				part->rgb = Color3f(part->rgb.r + v, part->rgb.g + v, part->rgb.b + v);
			}
		}
		
		Color color = (part->rgb * r).to<u8>();
		if(player.m_improve) {
			color.g = 0;
		}
		
		TextureContainer * tc = part->tc;
		if(tc == explo[0] && (part->m_flags & PARTICLE_ANIMATED)) {
			long animrange = part->cval2 - part->cval1;
			long num = long(float(framediff2) / float(part->tolive) * animrange);
			num = glm::clamp(num, long(part->cval1), long(part->cval2));
			tc = explo[num];
		}
		
		float siz = part->siz + part->scale.x * fd;

		RenderMaterial mat;
		mat.setTexture(tc);
		mat.setDepthTest(!(part->m_flags & PARTICLE_NOZBUFFER));
		
		if(part->m_flags & PARTICLE_SUB2) {
			mat.setBlendType(RenderMaterial::Subtractive2);
			color.a = glm::clamp(r * 1.5f, 0.f, 1.f) * 255;
		} else if(part->m_flags & SUBSTRACT) {
			mat.setBlendType(RenderMaterial::Subtractive);
		} else {
			mat.setBlendType(RenderMaterial::Additive);
		}
		
		if(part->m_flags & ROTATING) {
			if(!part->is2D) {
				float rott = MAKEANGLE(float(now + framediff2) * part->m_rotation);
				
				float temp = (part->zdec) ? 0.0001f : 2.f;
				float size = std::max(siz, 0.f);
				EERIEAddSprite(mat, in, size, color, temp, rott);
				
			}
		} else if(part->is2D) {
			
			float siz2 = part->siz + part->scale.y * fd;
			EERIEAddBitmap(mat, in, siz, siz2, tc, color);
			
		} else {
			
			float temp = (part->zdec) ? 0.0001f : 2.f;
			EERIEAddSprite(mat, in, siz, color, temp);
			
		}
		
		pcc--;
	}
}
예제 #2
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);
						}
					}
				}
			}
		}
	}
}
예제 #3
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();
	
	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 sphere;
		sphere.origin = actionPointPosition(io_weapon->obj, action.idx);
		sphere.radius = rad; 

		if(source != EntityHandle_Player)
			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))
				{
					bool HIT_SPARK = false;
					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) {
								ArxDuration ptime = ArxDurationMs(std::min(dmgs * 1000.f, paralyse));
								ARX_SPELLS_Launch(SPELL_PARALYSE,
								                  weapon,
								                  SPELLCAST_FLAG_NOMANA | SPELLCAST_FLAG_NOCHECKCANCAST,
								                  5,
								                  content,
								                  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);
								
								Vec3f vertPos = target->obj->vertexlist3[hitpoint].v;
								
								float power = (dmgs * ( 1.0f / 40 )) + 0.7f;
								
								Vec3f vect;
								vect.x = vertPos.x - io_source->pos.x;
								vect.y = 0;
								vect.z = vertPos.z - io_source->pos.z;
								vect = glm::normalize(vect);
								
								Sphere sp;
								sp.origin.x = vertPos.x + vect.x * 30.f;
								sp.origin.y = vertPos.y;
								sp.origin.z = vertPos.z + vect.z * 30.f;
								sp.radius = 3.5f * power * 20;

								if(CheckAnythingInSphere(sp, EntityHandle_Player, CAS_NO_NPC_COL)) {
									Color3f rgb = color.to<float>();
									
									Sphere splatSphere;
									splatSphere.origin = sp.origin;
									splatSphere.radius = 30.f;
									PolyBoomAddSplat(splatSphere, rgb, 1);
								}
							}

							ARX_PARTICLES_Spawn_Blood2(pos, dmgs, color, target);
						} else {
							if(target->ioflags & IO_ITEM)
								ParticleSparkSpawn(pos, Random::getu(0, 3), SpawnSparkType_Default);
							else
								ParticleSparkSpawn(pos, Random::getu(0, 30), SpawnSparkType_Default);

							ARX_NPC_SpawnAudibleSound(pos, io_source);

							if(io_source == entities.player())
								HIT_SPARK = true;
						}
					} 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::getu(0, 3);
						else
							nb = 30;

						if(target->ioflags & IO_ITEM)
							nb = 1;

						ParticleSparkSpawn(pos, nb, SpawnSparkType_Default);
						ARX_NPC_SpawnAudibleSound(pos, io_source);
						target->spark_n_blood = SP_SPARKING;

						if(!(target->ioflags & IO_NPC))
							HIT_SPARK = true;
					} 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::getu(0, 3);
						else
							nb = 30;

						if(target->ioflags & IO_ITEM)
							nb = 1;

						ParticleSparkSpawn(pos, nb, SpawnSparkType_Default);
						ARX_NPC_SpawnAudibleSound(pos, io_source);
						target->spark_n_blood = SP_SPARKING;

						if (!(target->ioflags & IO_NPC))
							HIT_SPARK = true;
					}

					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;
							}
							
							if(target->material != MATERIAL_NONE) {
								const char * matStr = ARX_MATERIAL_GetNameById(target->material);
								ARX_SOUND_PlayCollision(*weapon_material, matStr, 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);
				}
			}

			ParticleSparkSpawn(sphere.origin, Random::getu(0, 10), SpawnSparkType_Default);
			ARX_NPC_SpawnAudibleSound(sphere.origin, io_source);
		}
	}

	return ret;
}