static long ARX_THROWN_OBJECT_GetFree() { unsigned long latest_time = (unsigned long)(arxtime); long latest_obj = -1; for(size_t i = 0; i < MAX_THROWN_OBJECTS; i++) { if(Thrown[i].flags & ATO_EXIST) { if(Thrown[i].creation_time < latest_time) { latest_obj = i; latest_time = Thrown[i].creation_time; } } else { return i; } } if(latest_obj >= 0) { ARX_THROWN_OBJECT_Kill(latest_obj); return latest_obj; } return -1; }
static long ARX_THROWN_OBJECT_GetFree() { unsigned long latest_time = arxtime.now_ul(); long latest_obj = -1; for(size_t i = 0; i < MAX_THROWN_OBJECTS; i++) { if(g_projectiles[i].flags & ATO_EXIST) { if(g_projectiles[i].creation_time < latest_time) { latest_obj = i; latest_time = g_projectiles[i].creation_time; } } else { return i; } } if(latest_obj >= 0) { ARX_THROWN_OBJECT_Kill(latest_obj); return latest_obj; } return -1; }
void ARX_THROWN_OBJECT_Manage(unsigned long time_offset) { for(size_t i = 0; i < MAX_THROWN_OBJECTS; i++) { ARX_THROWN_OBJECT *thrownObj = &Thrown[i]; if(!(thrownObj->flags & ATO_EXIST)) continue; { // Is Object Visible & Near ? EERIE_BKG_INFO * bkgData = getFastBackgroundData(thrownObj->position.x, thrownObj->position.z); if(!bkgData || !bkgData->treat) { continue; } // Now render object ! if(!thrownObj->obj) continue; TransformInfo t(thrownObj->position, thrownObj->quat); DrawEERIEInter_ModelTransform(thrownObj->obj, t); if((thrownObj->flags & ATO_FIERY) && (thrownObj->flags & ATO_MOVING) && !(thrownObj->flags & ATO_UNDERWATER)) { LightHandle id = GetFreeDynLight(); if(lightHandleIsValid(id) && framedelay > 0) { EERIE_LIGHT * light = lightHandleGet(id); light->intensity = 1.f; light->fallstart = 100.f; light->fallend = 240.f; light->rgb = Color3f(1.f, .8f, .6f) - randomColor3f() * Color3f(.2f, .2f, .2f); light->pos = thrownObj->position; light->ex_flaresize = 40.f; light->extras |= EXTRAS_FLARE; light->duration = static_cast<long>(framedelay * 0.5f); } float p = 3.f; while(p > 0.f) { p -= 0.5f; if(thrownObj->obj) { long notok = 10; std::vector<EERIE_FACE>::iterator it; while(notok-- > 0) { it = Random::getIterator(thrownObj->obj->facelist); arx_assert(it != thrownObj->obj->facelist.end()); if(it->facetype & POLY_HIDE) continue; notok = -1; } if(notok < 0) { Vec3f pos = thrownObj->obj->vertexlist3[it->vid[0]].v; createFireParticles(pos, 2, 180); } } } } if(thrownObj->pRuban) { thrownObj->pRuban->SetNextPosition(thrownObj->position); thrownObj->pRuban->Update(time_offset); } Vec3f original_pos; if(thrownObj->flags & ATO_MOVING) { long need_kill = 0; float mod = (float)time_offset * thrownObj->velocity; original_pos = thrownObj->position; thrownObj->position.x += thrownObj->vector.x * mod; float gmod = 1.f - thrownObj->velocity; gmod = glm::clamp(gmod, 0.f, 1.f); thrownObj->position.y += thrownObj->vector.y * mod + (time_offset * gmod); thrownObj->position.z += thrownObj->vector.z * mod; CheckForIgnition(Sphere(original_pos, 10.f), 0, 2); Vec3f wpos = thrownObj->position; wpos.y += 20.f; EERIEPOLY * ep = EEIsUnderWater(wpos); if(thrownObj->flags & ATO_UNDERWATER) { if(!ep) { thrownObj->flags &= ~ATO_UNDERWATER; ARX_SOUND_PlaySFX(SND_PLOUF, &thrownObj->position); } } else if(ep) { thrownObj->flags |= ATO_UNDERWATER; ARX_SOUND_PlaySFX(SND_PLOUF, &thrownObj->position); } // Check for collision MUST be done after DRAWING !!!! long nbact = thrownObj->obj->actionlist.size(); for(long j = 0; j < nbact; j++) { float rad = GetHitValue(thrownObj->obj->actionlist[j].name); if(rad == -1) continue; rad *= .5f; const Vec3f v0 = thrownObj->obj->vertexlist3[thrownObj->obj->actionlist[j].idx].v; Vec3f dest = original_pos + thrownObj->vector * 95.f; Vec3f orgn = original_pos - thrownObj->vector * 25.f; EERIEPOLY * ep = CheckArrowPolyCollision(orgn, dest); if(ep) { ARX_PARTICLES_Spawn_Spark(v0, 14, 0); CheckExp(i); if(ValidIONum(thrownObj->source)) ARX_NPC_SpawnAudibleSound(v0, entities[thrownObj->source]); thrownObj->flags &= ~ATO_MOVING; thrownObj->velocity = 0.f; std::string bkg_material = "earth"; if(ep && ep->tex && !ep->tex->m_texName.empty()) bkg_material = GetMaterialString(ep->tex->m_texName); if(ValidIONum(thrownObj->source)) { char weapon_material[64] = "dagger"; ARX_SOUND_PlayCollision(weapon_material, bkg_material, 1.f, 1.f, v0, entities[thrownObj->source]); } thrownObj->position = original_pos; j = 200; } else if(IsPointInField(v0)) { ARX_PARTICLES_Spawn_Spark(v0, 24, 0); CheckExp(i); if (ValidIONum(thrownObj->source)) ARX_NPC_SpawnAudibleSound(v0, entities[thrownObj->source]); thrownObj->flags &= ~ATO_MOVING; thrownObj->velocity = 0.f; if(ValidIONum(thrownObj->source)) { char weapon_material[64] = "dagger"; char bkg_material[64] = "earth"; ARX_SOUND_PlayCollision(weapon_material, bkg_material, 1.f, 1.f, v0, entities[thrownObj->source]); } thrownObj->position = original_pos; j = 200; need_kill = 1; } else { for(float precision = 0.5f; precision <= 6.f; precision += 0.5f) { Sphere sphere; sphere.origin = v0 + thrownObj->vector * precision * 4.5f; sphere.radius = rad + 3.f; std::vector<EntityHandle> sphereContent; if(CheckEverythingInSphere(sphere, thrownObj->source, EntityHandle::Invalid, sphereContent)) { for(size_t jj = 0; jj < sphereContent.size(); jj++) { if(ValidIONum(sphereContent[jj]) && sphereContent[jj] != thrownObj->source) { Entity * target = entities[sphereContent[jj]]; if(target->ioflags & IO_NPC) { Vec3f pos; Color color = Color::none; long hitpoint = -1; float curdist = 999999.f; for(size_t ii = 0 ; ii < target->obj->facelist.size() ; ii++) { if(target->obj->facelist[ii].facetype & POLY_HIDE) continue; short vid = target->obj->facelist[ii].vid[0]; float d = glm::distance(sphere.origin, target->obj->vertexlist3[vid].v); if(d < curdist) { hitpoint = target->obj->facelist[ii].vid[0]; curdist = d; } } if(hitpoint >= 0) { color = target->_npcdata->blood_color; pos = target->obj->vertexlist3[hitpoint].v; } if(thrownObj->source == 0) { float damages = ARX_THROWN_ComputeDamages(i, thrownObj->source, sphereContent[jj]); if(damages > 0.f) { arx_assert(hitpoint >= 0); if(target->ioflags & IO_NPC) { target->_npcdata->SPLAT_TOT_NB = 0; ARX_PARTICLES_Spawn_Blood2(original_pos, damages, color, target); } ARX_PARTICLES_Spawn_Blood2(pos, damages, color, target); ARX_DAMAGES_DamageNPC(target, damages, thrownObj->source, false, &pos); if(Random::getf(0.f, 100.f) > target->_npcdata->resist_poison) { target->_npcdata->poisonned += thrownObj->poisonous; } CheckExp(i); } else { ARX_PARTICLES_Spawn_Spark(v0, 14, 0); ARX_NPC_SpawnAudibleSound(v0, entities[thrownObj->source]); } } } else { // not NPC if(target->ioflags & IO_FIX) { if(ValidIONum(thrownObj->source)) ARX_DAMAGES_DamageFIX(target, 0.1f, thrownObj->source, false); } ARX_PARTICLES_Spawn_Spark(v0, 14, 0); if(ValidIONum(thrownObj->source)) ARX_NPC_SpawnAudibleSound(v0, entities[thrownObj->source]); CheckExp(i); } // Need to deal damages ! thrownObj->flags &= ~ATO_MOVING; thrownObj->velocity = 0.f; need_kill = 1; precision = 500.f; j = 200; } } } } } } if(need_kill) ARX_THROWN_OBJECT_Kill(i); } } } }
void ARX_THROWN_OBJECT_KillAll() { for(size_t i = 0; i < MAX_THROWN_OBJECTS; i++) { ARX_THROWN_OBJECT_Kill(i); } }