Exemple #1
0
bool ARX_DAMAGES_TryToDoDamage(const Vec3f & pos, float dmg, float radius, EntityHandle source)
{
	bool ret = false;

	for(size_t i = 0; i < entities.size(); i++) {
		const EntityHandle handle = EntityHandle(i);
		Entity * io = entities[handle];

		if(io != NULL
		   && (entities[handle]->gameFlags & GFLAG_ISINTREATZONE)
		   && io->show == SHOW_FLAG_IN_SCENE
		   && source != handle
		) {
			float threshold;
			float rad = radius + 5.f;

			if(io->ioflags & IO_FIX) {
				threshold = 510;
				rad += 10.f;
			} else if(io->ioflags & IO_NPC) {
				threshold = 250;
			} else {
				threshold = 350;
			}

			if(closerThan(pos, io->pos, threshold) && SphereInIO(io, Sphere(pos, rad))) {
				if(io->ioflags & IO_NPC) {
					if(ValidIONum(source))
						ARX_EQUIPMENT_ComputeDamages(entities[source], io, 1.f);

					ret = true;
				}

				if(io->ioflags & IO_FIX) {
					ARX_DAMAGES_DamageFIX(io, dmg, source, false);
					ret = true;
				}
			}
		}
	}

	return ret;
}
//***********************************************************************************************
// flags & 1 = blood spawn only
//-----------------------------------------------------------------------------------------------
//***********************************************************************************************
bool ARX_EQUIPMENT_Strike_Check(Entity * io_source, Entity * io_weapon, float ratioaim, long flags, EntityHandle targ) {
	
	ARX_PROFILE_FUNC();
	
	arx_assert(io_source);
	arx_assert(io_weapon);
	
	bool ret = false;
	EntityHandle source = io_source->index();
	EntityHandle weapon = io_weapon->index();
	Sphere sphere;

	EXCEPTIONS_LIST_Pos = 0;

	float drain_life = ARX_EQUIPMENT_GetSpecialValue(io_weapon, IO_SPECIAL_ELEM_DRAIN_LIFE);
	float paralyse = ARX_EQUIPMENT_GetSpecialValue(io_weapon, IO_SPECIAL_ELEM_PARALYZE);

	BOOST_FOREACH(const EERIE_ACTIONLIST & action, io_weapon->obj->actionlist) {
		
		float rad = GetHitValue(action.name);

		if(rad == -1)
			continue;
		
		sphere.origin = actionPointPosition(io_weapon->obj, action.idx);
		sphere.radius = rad; 

		if(source != PlayerEntityHandle)
			sphere.radius += 15.f;

		std::vector<EntityHandle> sphereContent;

		if(CheckEverythingInSphere(sphere, source, targ, sphereContent)) {
			BOOST_FOREACH(const EntityHandle & content, sphereContent) {
				if(ValidIONum(content)
						&& !(entities[content]->ioflags & IO_BODY_CHUNK))
				{
					long HIT_SPARK = 0;
					EXCEPTIONS_LIST[EXCEPTIONS_LIST_Pos] = content;
					EXCEPTIONS_LIST_Pos++;

					if(EXCEPTIONS_LIST_Pos >= MAX_IN_SPHERE)
						EXCEPTIONS_LIST_Pos--;

					Entity * target = entities[content];
			
					Vec3f pos;
					Color color = Color::white;
					long hitpoint = -1;
					float curdist = 999999.f;
					
					Vec3f vector = (sphere.origin - target->pos) * Vec3f(1.f, 0.5f, 1.f);
					vector = glm::normalize(vector);

					for(size_t ii = 0; ii < target->obj->facelist.size(); ii++) {
						if(target->obj->facelist[ii].facetype & POLY_HIDE)
							continue;

						float d = glm::distance(sphere.origin, target->obj->vertexlist3[target->obj->facelist[ii].vid[0]].v);

						if(d < curdist) {
							hitpoint = target->obj->facelist[ii].vid[0];
							curdist = d;
						}
					}

					if(hitpoint >= 0) {
						color = (target->ioflags & IO_NPC) ? target->_npcdata->blood_color : Color::white;
						pos = target->obj->vertexlist3[hitpoint].v;
					}
					else ARX_DEAD_CODE(); 
					
					float dmgs = 0.f;
					if(!(flags & 1)) {
						Vec3f posi;

						if(hitpoint >= 0) {
							posi = target->obj->vertexlist3[hitpoint].v;
							dmgs = ARX_EQUIPMENT_ComputeDamages(io_source, target, ratioaim, &posi);
						} else {
							dmgs = ARX_EQUIPMENT_ComputeDamages(io_source, target, ratioaim);
						}

						if(target->ioflags & IO_NPC) {
							ret = true;
							target->spark_n_blood = 0;
							target->_npcdata->SPLAT_TOT_NB = 0;

							if(drain_life > 0.f) {
								float life_gain = std::min(dmgs, drain_life);
								life_gain = std::min(life_gain, target->_npcdata->lifePool.current);
								life_gain = std::max(life_gain, 0.f);
								ARX_DAMAGES_HealInter(io_source, life_gain);
							}

							if(paralyse > 0.f) {
								float ptime = std::min(dmgs * 1000.f, paralyse);
								ARX_SPELLS_Launch(SPELL_PARALYSE, weapon, SPELLCAST_FLAG_NOMANA | SPELLCAST_FLAG_NOCHECKCANCAST
												  , 5, content, (long)(ptime));
							}
						}

						if(io_source == entities.player())
							ARX_DAMAGES_DurabilityCheck(io_weapon, 0.2f);
					}

					if(dmgs > 0.f || ((target->ioflags & IO_NPC) && target->spark_n_blood == SP_BLOODY)) {
						if(target->ioflags & IO_NPC) {
							target->spark_n_blood = SP_BLOODY;

							if(!(flags & 1)) {
								ARX_PARTICLES_Spawn_Splat(pos, dmgs, color);

								Sphere sp;
								float power;
								power = (dmgs * ( 1.0f / 40 )) + 0.7f;
								Vec3f vect;
								vect.x = target->obj->vertexlist3[hitpoint].v.x - io_source->pos.x;
								vect.y = 0;
								vect.z = target->obj->vertexlist3[hitpoint].v.z - io_source->pos.z;
								vect = glm::normalize(vect);
								sp.origin.x = target->obj->vertexlist3[hitpoint].v.x + vect.x * 30.f;
								sp.origin.y = target->obj->vertexlist3[hitpoint].v.y;
								sp.origin.z = target->obj->vertexlist3[hitpoint].v.z + vect.z * 30.f;
								sp.radius = 3.5f * power * 20;

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

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

							ARX_NPC_SpawnAudibleSound(pos, io_source);

							if(io_source == entities.player())
								HIT_SPARK = 1;
						}
					} else if((target->ioflags & IO_NPC) && (dmgs <= 0.f || target->spark_n_blood == SP_SPARKING)) {
						unsigned int nb;

						if(target->spark_n_blood == SP_SPARKING)
							nb = Random::get(0, 3);
						else
							nb = 30;

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

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

						if(!(target->ioflags & IO_NPC))
							HIT_SPARK = 1;
					} else if(dmgs <= 0.f && ((target->ioflags & IO_FIX) || (target->ioflags & IO_ITEM))) {
						unsigned int nb;

						if(target->spark_n_blood == SP_SPARKING)
							nb = Random::get(0, 3);
						else
							nb = 30;

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

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

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

					if(HIT_SPARK) {
						if(!io_source->isHit) {
							ARX_DAMAGES_DurabilityCheck(io_weapon, 1.f);
							io_source->isHit = true;
							
								std::string _weapon_material = "metal";
								const std::string * weapon_material = &_weapon_material;

								if(!io_weapon->weaponmaterial.empty()) {
									weapon_material = &io_weapon->weaponmaterial;
								}

								char bkg_material[128];

								if(ARX_MATERIAL_GetNameById(target->material, bkg_material))
									ARX_SOUND_PlayCollision(*weapon_material, bkg_material, 1.f, 1.f, sphere.origin, NULL);
						}
					}
				}
			}
		}

		const EERIEPOLY * ep = CheckBackgroundInSphere(sphere);
		if(ep) {
			if(io_source == entities.player()) {
				if(!io_source->isHit) {
					ARX_DAMAGES_DurabilityCheck(io_weapon, 1.f);
					io_source->isHit = true;
					
						std::string _weapon_material = "metal";
						const std::string * weapon_material = &_weapon_material;
						if(!io_weapon->weaponmaterial.empty()) {
							weapon_material = &io_weapon->weaponmaterial;
						}

						std::string bkg_material = "earth";

						if(ep && ep->tex && !ep->tex->m_texName.empty())
							bkg_material = GetMaterialString(ep->tex->m_texName);

						ARX_SOUND_PlayCollision(*weapon_material, bkg_material, 1.f, 1.f, sphere.origin, io_source);
				}
			}

			ARX_PARTICLES_Spawn_Spark(sphere.origin, Random::get(0, 10), SpawnSparkType_Default);
			ARX_NPC_SpawnAudibleSound(sphere.origin, io_source);
		}
	}

	return ret;
}