static ObjSelection GetCutSelection(Entity * io, DismembermentFlag flag) { if(!io || !(io->ioflags & IO_NPC) || flag == 0) return ObjSelection(); std::string tx; if (flag == FLAG_CUT_HEAD) tx = "cut_head"; else if (flag == FLAG_CUT_TORSO) tx = "cut_torso"; else if (flag == FLAG_CUT_LARM) tx = "cut_larm"; if (flag == FLAG_CUT_RARM) tx = "cut_rarm"; if (flag == FLAG_CUT_LLEG) tx = "cut_lleg"; if (flag == FLAG_CUT_RLEG) tx = "cut_rleg"; if ( !tx.empty() ) { typedef std::vector<EERIE_SELECTIONS>::iterator iterator; // Convenience for(iterator iter = io->obj->selections.begin(); iter != io->obj->selections.end(); ++iter) { if(iter->selected.size() > 0 && iter->name == tx) { return ObjSelection(iter - io->obj->selections.begin()); } } } return ObjSelection(); }
ObjSelection EERIE_OBJECT_GetSelection(const EERIE_3DOBJ * obj, const std::string & selname) { if(!obj) return ObjSelection(); for(size_t i = 0; i < obj->selections.size(); i++) { if(obj->selections[i].name == selname) { return ObjSelection(i); } } return ObjSelection(); }
static bool ARX_NPC_ApplyCuts(Entity * io) { if(!io || !(io->ioflags & IO_NPC)) return false; if(io->_npcdata->cuts == 0) return false; // No cuts ReComputeCutFlags(io); long goretex = -1; for(size_t i = 0; i < io->obj->texturecontainer.size(); i++) { if (io->obj->texturecontainer[i] && (boost::contains(io->obj->texturecontainer[i]->m_texName.string(), "gore"))) { goretex = i; break; } } bool hid = false; for(size_t nn = 0; nn < io->obj->facelist.size(); nn++) { io->obj->facelist[nn].facetype &= ~POLY_HIDE; } for(long jj = 0; jj < 6; jj++) { DismembermentFlag flg = DismembermentFlag(1 << jj); ObjSelection numsel = GetCutSelection(io, flg); if((io->_npcdata->cuts & flg) && numsel != ObjSelection()) { for(size_t ll = 0; ll < io->obj->facelist.size(); ll++) { EERIE_FACE & face = io->obj->facelist[ll]; if( IsInSelection(io->obj, face.vid[0], numsel) || IsInSelection(io->obj, face.vid[1], numsel) || IsInSelection(io->obj, face.vid[2], numsel) ) { if(!(face.facetype & POLY_HIDE)) { if(face.texid != goretex) hid = true; } face.facetype |= POLY_HIDE; } } io->_npcdata->cut = 1; } } return hid; }
bool IsInSelection(const EERIE_3DOBJ * obj, size_t vert, ObjSelection tw) { if(!obj || tw == ObjSelection()) return false; const EERIE_SELECTIONS & sel = obj->selections[tw.handleData()]; for(size_t i = 0; i < sel.selected.size(); i++) { if(sel.selected[i] == vert) return true; } return false; }
static bool IsNearSelection(EERIE_3DOBJ * obj, long vert, ObjSelection tw) { if(!obj || tw == ObjSelection() || vert < 0) return false; const EERIE_SELECTIONS & sel = obj->selections[tw.handleData()]; for(size_t i = 0; i < sel.selected.size(); i++) { float d = glm::distance(obj->vertexlist[sel.selected[i]].v, obj->vertexlist[vert].v); if(d < 8.f) return true; } return false; }
static EERIE_3DOBJ * CreateIntermediaryMesh(const EERIE_3DOBJ * obj1, const EERIE_3DOBJ * obj2, long tw) { ObjSelection tw1 = ObjSelection(); ObjSelection tw2 = ObjSelection(); ObjSelection iw1 = ObjSelection(); ObjSelection jw1 = ObjSelection(); ObjSelection sel_head1 = ObjSelection(); ObjSelection sel_head2 = ObjSelection(); ObjSelection sel_torso1 = ObjSelection(); ObjSelection sel_torso2 = ObjSelection(); ObjSelection sel_legs1 = ObjSelection(); ObjSelection sel_legs2 = ObjSelection(); // First we retreive selection groups indexes for(size_t i = 0; i < obj1->selections.size(); i++) { // TODO iterator ObjSelection sel = ObjSelection(i); if(obj1->selections[i].name == "head") { sel_head1 = sel; } else if(obj1->selections[i].name == "chest") { sel_torso1 = sel; } else if(obj1->selections[i].name == "leggings") { sel_legs1 = sel; } } for(size_t i = 0; i < obj2->selections.size(); i++) { // TODO iterator ObjSelection sel = ObjSelection(i); if(obj2->selections[i].name == "head") { sel_head2 = sel; } else if(obj2->selections[i].name == "chest") { sel_torso2 = sel; } else if(obj2->selections[i].name == "leggings") { sel_legs2 = sel; } } if(sel_head1 == ObjSelection()) return NULL; if(sel_head2 == ObjSelection()) return NULL; if(sel_torso1 == ObjSelection()) return NULL; if(sel_torso2 == ObjSelection()) return NULL; if(sel_legs1 == ObjSelection()) return NULL; if(sel_legs2 == ObjSelection()) return NULL; if(tw == TWEAK_HEAD) { tw1 = sel_head1; tw2 = sel_head2; iw1 = sel_torso1; jw1 = sel_legs1; } if(tw == TWEAK_TORSO) { tw1 = sel_torso1; tw2 = sel_torso2; iw1 = sel_head1; jw1 = sel_legs1; } if(tw == TWEAK_LEGS) { tw1 = sel_legs1; tw2 = sel_legs2; iw1 = sel_torso1; jw1 = sel_head1; } if(tw1 == ObjSelection() || tw2 == ObjSelection()) return NULL; // Now Retreives Tweak Action Points { ActionPoint idx_head1 = GetActionPoint(obj1, "head2chest"); if(idx_head1 == ActionPoint()) return NULL; ActionPoint idx_head2 = GetActionPoint(obj2, "head2chest"); if(idx_head2 == ActionPoint()) return NULL; ActionPoint idx_torso1 = GetActionPoint(obj1, "chest2leggings"); if(idx_torso1 == ActionPoint()) return NULL; ActionPoint idx_torso2 = GetActionPoint(obj2, "chest2leggings"); if(idx_torso2 == ActionPoint()) return NULL; } // copy vertices std::vector<EERIE_VERTEX> obj1vertexlist2 = obj1->vertexlist; std::vector<EERIE_VERTEX> obj2vertexlist2 = obj2->vertexlist; // Work will contain the Tweaked object EERIE_3DOBJ * work = new EERIE_3DOBJ; work->pos = obj1->pos; work->angle = obj1->angle; // We reset all data to create a fresh object work->cub = obj1->cub; work->quat = obj1->quat; // Linked objects are linked to this object. if(obj1->linked.size() > obj2->linked.size()) { work->linked = obj1->linked; } else { work->linked = obj2->linked; } // Is the origin of object in obj1 or obj2 ? Retreives it for work object if(IsInSelection(obj1, obj1->origin, tw1)) { work->point0 = obj2->point0; work->origin = ObjectAddVertex(work, &obj2vertexlist2[obj2->origin]); } else { work->point0 = obj1->point0; work->origin = ObjectAddVertex(work, &obj1vertexlist2[obj1->origin]); } // Recreate Action Points included in work object.for Obj1 for(size_t i = 0; i < obj1->actionlist.size(); i++) { const EERIE_ACTIONLIST & action = obj1->actionlist[i]; if( IsInSelection(obj1, action.idx.handleData(), iw1) || IsInSelection(obj1, action.idx.handleData(), jw1) || action.name == "head2chest" || action.name == "chest2leggings" ) { ObjectAddAction(work, action.name, action.act, action.sfx, &obj1vertexlist2[action.idx.handleData()]); } } // Do the same for Obj2 for(size_t i = 0; i < obj2->actionlist.size(); i++) { const EERIE_ACTIONLIST & action = obj2->actionlist[i]; if( IsInSelection(obj2, action.idx.handleData(), tw2) || action.name == "head2chest" || action.name == "chest2leggings" ) { ObjectAddAction(work, action.name, action.act, action.sfx, &obj2vertexlist2[action.idx.handleData()]); } } // Recreate Vertex using Obj1 Vertexes for(size_t i = 0; i < obj1->vertexlist.size(); i++) { if(IsInSelection(obj1, i, iw1) || IsInSelection(obj1, i, jw1)) { ObjectAddVertex(work, &obj1vertexlist2[i]); } } // The same for Obj2 for(size_t i = 0; i < obj2->vertexlist.size(); i++) { if(IsInSelection(obj2, i, tw2)) { ObjectAddVertex(work, &obj2vertexlist2[i]); } } // Look in Faces for forgotten Vertexes... AND // Re-Create TextureContainers Infos // We look for texturecontainers included in the future tweaked object TextureContainer * tc = NULL; for(size_t i = 0; i < obj1->facelist.size(); i++) { const EERIE_FACE & face = obj1->facelist[i]; if( (IsInSelection(obj1, face.vid[0], iw1) || IsInSelection(obj1, face.vid[0], jw1)) && (IsInSelection(obj1, face.vid[1], iw1) || IsInSelection(obj1, face.vid[1], jw1)) && (IsInSelection(obj1, face.vid[2], iw1) || IsInSelection(obj1, face.vid[2], jw1)) ) { if(face.texid != -1) { if(tc != obj1->texturecontainer[face.texid]) { tc = obj1->texturecontainer[face.texid]; ObjectAddMap(work, tc); } } ObjectAddFace(work, &face, obj1); } } for(size_t i = 0; i < obj2->facelist.size(); i++) { const EERIE_FACE & face = obj2->facelist[i]; if( IsInSelection(obj2, face.vid[0], tw2) || IsInSelection(obj2, face.vid[1], tw2) || IsInSelection(obj2, face.vid[2], tw2) ) { if(face.texid != -1) { if(tc != obj2->texturecontainer[face.texid]) { tc = obj2->texturecontainer[face.texid]; ObjectAddMap(work, tc); } } ObjectAddFace(work, &face, obj2); } } // Recreate Groups work->grouplist.resize(std::max(obj1->grouplist.size(), obj2->grouplist.size())); for(size_t k = 0; k < obj1->grouplist.size(); k++) { const VertexGroup & grp = obj1->grouplist[k]; work->grouplist[k].name = grp.name; long v = GetEquivalentVertex(work, &obj1vertexlist2[grp.origin]); if(v >= 0) { work->grouplist[k].siz = grp.siz; if(IsInSelection(obj1, grp.origin, iw1) || IsInSelection(obj1, grp.origin, jw1)) work->grouplist[k].origin = v; } } for(size_t k = 0; k < obj2->grouplist.size(); k++) { if(k >= obj1->grouplist.size()) { work->grouplist[k].name = obj2->grouplist[k].name; } long v = GetEquivalentVertex(work, &obj2vertexlist2[obj2->grouplist[k].origin]); if(v >= 0) { work->grouplist[k].siz = obj2->grouplist[k].siz; if(IsInSelection(obj2, obj2->grouplist[k].origin, tw2)) work->grouplist[k].origin = v; } } // Recreate Selection Groups (only the 3 selections needed to reiterate MeshTweaking !) work->selections.resize(3); work->selections[0].name = "head"; work->selections[1].name = "chest"; work->selections[2].name = "leggings"; // Re-Creating sel_head if(tw == TWEAK_HEAD) { const EERIE_SELECTIONS & sel = obj2->selections[sel_head2.handleData()]; for(size_t l = 0; l < sel.selected.size(); l++) { EERIE_VERTEX temp; temp.v = obj2vertexlist2[sel.selected[l]].v; long t = GetEquivalentVertex(work, &temp); if(t != -1) { ObjectAddSelection(work, 0, t); } } } else { const EERIE_SELECTIONS & sel = obj1->selections[sel_head1.handleData()]; for(size_t l = 0; l < sel.selected.size(); l++) { EERIE_VERTEX temp; temp.v = obj1vertexlist2[sel.selected[l]].v; long t = GetEquivalentVertex(work, &temp); if(t != -1) { ObjectAddSelection(work, 0, t); } } } // Re-Create sel_torso if(tw == TWEAK_TORSO) { const EERIE_SELECTIONS & sel = obj2->selections[sel_torso2.handleData()]; for(size_t l = 0; l < sel.selected.size(); l++) { EERIE_VERTEX temp; temp.v = obj2vertexlist2[sel.selected[l]].v; long t = GetEquivalentVertex(work, &temp); if(t != -1) { ObjectAddSelection(work, 1, t); } } } else { const EERIE_SELECTIONS & sel = obj1->selections[sel_torso1.handleData()]; for(size_t l = 0; l < sel.selected.size(); l++) { EERIE_VERTEX temp; temp.v = obj1vertexlist2[sel.selected[l]].v; long t = GetEquivalentVertex(work, &temp); if(t != -1) { ObjectAddSelection(work, 1, t); } } } // Re-Create sel_legs if(tw == TWEAK_LEGS) { const EERIE_SELECTIONS & sel = obj2->selections[sel_legs2.handleData()]; for(size_t l = 0; l < sel.selected.size(); l++) { EERIE_VERTEX temp; temp.v = obj2vertexlist2[sel.selected[l]].v; long t = GetEquivalentVertex(work, &temp); if(t != -1) { ObjectAddSelection(work, 2, t); } } } else { const EERIE_SELECTIONS & sel = obj1->selections[sel_legs1.handleData()]; for(size_t l = 0; l < sel.selected.size(); l++) { EERIE_VERTEX temp; temp.v = obj1vertexlist2[sel.selected[l]].v; long t = GetEquivalentVertex(work, &temp); if(t != -1) { ObjectAddSelection(work, 2, t); } } } //Now recreates other selections... for(size_t i = 0; i < obj1->selections.size(); i++) { if(EERIE_OBJECT_GetSelection(work, obj1->selections[i].name) == ObjSelection()) { size_t num = work->selections.size(); work->selections.resize(num + 1); work->selections[num].name = obj1->selections[i].name; for(size_t l = 0; l < obj1->selections[i].selected.size(); l++) { EERIE_VERTEX temp; temp.v = obj1vertexlist2[obj1->selections[i].selected[l]].v; long t = GetEquivalentVertex(work, &temp); if (t != -1) { ObjectAddSelection(work, num, t); } } ObjSelection ii = EERIE_OBJECT_GetSelection(obj2, obj1->selections[i].name); if(ii != ObjSelection()) { const EERIE_SELECTIONS & sel = obj2->selections[ii.handleData()]; for(size_t l = 0; l < sel.selected.size(); l++) { EERIE_VERTEX temp; temp.v = obj2vertexlist2[sel.selected[l]].v; long t = GetEquivalentVertex(work, &temp); if(t != -1) { ObjectAddSelection(work, num, t); } } } } } for(size_t i = 0; i < obj2->selections.size(); i++) { if(EERIE_OBJECT_GetSelection(work, obj2->selections[i].name) == ObjSelection()) { size_t num = work->selections.size(); work->selections.resize(num + 1); work->selections[num].name = obj2->selections[i].name; for(size_t l = 0; l < obj2->selections[i].selected.size(); l++) { EERIE_VERTEX temp; temp.v = obj2vertexlist2[obj2->selections[i].selected[l]].v; long t = GetEquivalentVertex(work, &temp); if(t != -1) { ObjectAddSelection(work, num, t); } } } } // Recreate Animation-groups vertex for(size_t i = 0; i < obj1->grouplist.size(); i++) { for(size_t j = 0; j < obj1->grouplist[i].indexes.size(); j++) { AddVertexToGroup(work, i, &obj1vertexlist2[obj1->grouplist[i].indexes[j]]); } } for(size_t i = 0; i < obj2->grouplist.size(); i++) { for(size_t j = 0; j < obj2->grouplist[i].indexes.size(); j++) { AddVertexToGroup(work, i, &obj2vertexlist2[obj2->grouplist[i].indexes[j]]); } } work->vertexWorldPositions.resize(work->vertexlist.size()); work->vertexClipPositions.resize(work->vertexlist.size()); work->vertexColors.resize(work->vertexlist.size()); return work; }
// TODO copy-paste halo static void AddAnimatedObjectHalo(HaloInfo & haloInfo, const unsigned short * paf, float invisibility, EERIE_3DOBJ * eobj, Entity * io, TexturedVertex * tvList) { IO_HALO * curhalo = NULL; for(size_t h = 0; h < haloInfo.size; h++) { const HaloRenderInfo & entry = haloInfo.entries[h]; if(entry.selection == ObjSelection() || IsInSelection(eobj, paf[0], entry.selection)) { curhalo = entry.halo; break; } } if(!curhalo) return; float tot = 0; float _ffr[3]; ColorRGBA colors[3]; for(size_t o = 0; o < 3; o++) { float tttz = glm::abs(eobj->vertexlist3[paf[o]].norm.z) * ( 1.0f / 2 ); float power = 255.f - (float)(255.f * tttz); power *= (1.f - invisibility); power = glm::clamp(power, 0.f, 255.f); tot += power; _ffr[o] = power; u8 lfr = curhalo->color.r * power; u8 lfg = curhalo->color.g * power; u8 lfb = curhalo->color.b * power; colors[o] = Color(lfr, lfg, lfb, 255).toRGBA(); } if(tot > 260) { long first; long second; long third; if(_ffr[0] >= _ffr[1] && _ffr[1] >= _ffr[2]) { first = 0; second = 1; third = 2; } else if(_ffr[0] >= _ffr[2] && _ffr[2] >= _ffr[1]) { first = 0; second = 2; third = 1; } else if(_ffr[1] >= _ffr[0] && _ffr[0] >= _ffr[2]) { first = 1; second = 0; third = 2; } else if(_ffr[1] >= _ffr[2] && _ffr[2] >= _ffr[0]) { first = 1; second = 2; third = 0; } else if(_ffr[2] >= _ffr[0] && _ffr[0] >= _ffr[1]) { first = 2; second = 0; third = 1; } else { first = 2; second = 1; third = 0; } if(_ffr[first] > 150.f && _ffr[second] > 110.f) { TexturedVertex vert[4]; vert[0] = tvList[first]; vert[1] = tvList[first]; vert[2] = tvList[second]; vert[3] = tvList[second]; vert[0].color = colors[first]; vert[1].color = colors[first]; vert[2].color = colors[second]; vert[3].color = colors[second]; float siz = haloInfo.ddist * (curhalo->radius * (std::sin(arxtime.get_frame_time() * .01f) * .1f + 1.f)) * .6f; if(io == entities.player() && haloInfo.ddist > 0.8f && !EXTERNALVIEW) siz *= 1.5f; Vec3f vect1; vect1.x = tvList[first].p.x - tvList[third].p.x; vect1.y = tvList[first].p.y - tvList[third].p.y; float len1 = 2.f / ffsqrt(vect1.x * vect1.x + vect1.y * vect1.y); if(vect1.x < 0.f) len1 *= 1.2f; vect1.x *= len1; vect1.y *= len1; Vec3f vect2; vect2.x = tvList[second].p.x - tvList[third].p.x; vect2.y = tvList[second].p.y - tvList[third].p.y; float len2 = 1.f / ffsqrt(vect2.x * vect2.x + vect2.y * vect2.y); if(vect2.x < 0.f) len2 *= 1.2f; vect2.x *= len2; vect2.y *= len2; vert[1].p.x += (vect1.x + Random::getf(0.1f, 0.2f)) * siz; vert[1].p.y += (vect1.y + Random::getf(0.1f, 0.2f)) * siz; vert[1].color = Color(0, 0, 0, 255).toRGBA(); float valll; valll = 0.005f + (glm::abs(tvList[first].p.z) - glm::abs(tvList[third].p.z)) + (glm::abs(tvList[second].p.z) - glm::abs(tvList[third].p.z)); valll = 0.0001f + valll * ( 1.0f / 10 ); if(valll < 0.f) valll = 0.f; vert[1].p.z += valll; vert[2].p.z += valll; vert[0].p.z += 0.0001f; vert[3].p.z += 0.0001f;//*( 1.0f / 2 ); vert[1].rhw *= .98f; vert[2].rhw *= .98f; vert[0].rhw *= .98f; vert[3].rhw *= .98f; vert[2].p.x += (vect2.x + Random::getf(0.1f, 0.2f)) * siz; vert[2].p.y += (vect2.y + Random::getf(0.1f, 0.2f)) * siz; vert[1].p.z = (vert[1].p.z + haloInfo.MAX_ZEDE) * ( 1.0f / 2 ); vert[2].p.z = (vert[2].p.z + haloInfo.MAX_ZEDE) * ( 1.0f / 2 ); if(curhalo->flags & HALO_NEGATIVE) vert[2].color = Color(0, 0, 0, 0).toRGBA(); else vert[2].color = Color(0, 0, 0, 255).toRGBA(); Halo_AddVertices(vert); } } }
//! \brief Recreates player mesh from scratch static void applyTweak(EquipmentSlot equip, TweakType tw, const std::string & selection) { if(!ValidIONum(player.equiped[equip])) { return; } Entity * io = entities.player(); arx_assert(entities[player.equiped[equip]]->tweakerinfo != NULL); const IO_TWEAKER_INFO & tweak = *entities[player.equiped[equip]]->tweakerinfo; if(!tweak.filename.empty()) { res::path mesh = "graph/obj3d/interactive/npc/human_base/tweaks" / tweak.filename; EERIE_MESH_TWEAK_Do(io, tw, mesh); } if(tweak.skintochange.empty() || tweak.skinchangeto.empty()) { return; } res::path file = "graph/obj3d/textures" / tweak.skinchangeto; TextureContainer * temp = TextureContainer::Load(file, TextureContainer::Level); long mapidx = ObjectAddMap(io->obj, temp); ObjSelection sel = ObjSelection(); for(size_t i = 0; i < io->obj->selections.size(); i++) { if(io->obj->selections[i].name == selection) { sel = ObjSelection(i); break; } } if(sel == ObjSelection()) { return; } long textochange = -1; for(size_t i = 0; i < io->obj->texturecontainer.size(); i++) { if(tweak.skintochange == io->obj->texturecontainer[i]->m_texName.filename()) { textochange = i; } } if(textochange == -1) { return; } for(size_t i = 0; i < io->obj->facelist.size(); i++) { EERIE_FACE & face = io->obj->facelist[i]; if( IsInSelection(io->obj, face.vid[0], sel) && IsInSelection(io->obj, face.vid[1], sel) && IsInSelection(io->obj, face.vid[2], sel) ) { if(face.texid == textochange) { face.texid = (short)mapidx; } } } }
/*! * \brief Spawns a body part from NPC * \param ioo * \param num */ static void ARX_NPC_SpawnMember(Entity * ioo, ObjSelection num) { if(!ioo) return; EERIE_3DOBJ * from = ioo->obj; if(!from || num == ObjSelection() || (size_t)num.handleData() >= from->selections.size()) return; EERIE_3DOBJ * nouvo = new EERIE_3DOBJ; if(!nouvo) return; size_t nvertex = from->selections[num.handleData()].selected.size(); long gore = -1; for(size_t k = 0; k < from->texturecontainer.size(); k++) { if(from->texturecontainer[k] && boost::contains(from->texturecontainer[k]->m_texName.string(), "gore")) { gore = k; break; } } for(size_t k = 0; k < from->facelist.size(); k++) { if(from->facelist[k].texid == gore) { if( IsNearSelection(from, from->facelist[k].vid[0], num) || IsNearSelection(from, from->facelist[k].vid[1], num) || IsNearSelection(from, from->facelist[k].vid[2], num) ) { nvertex += 3; } } } nouvo->vertexlist.resize(nvertex); nouvo->vertexlist3.resize(nvertex); long inpos = 0; long * equival = (long *)malloc(sizeof(long) * from->vertexlist.size()); if(!equival) { delete nouvo; return; } for(size_t k = 0; k < from->vertexlist.size(); k++) { equival[k] = -1; } const EERIE_SELECTIONS & cutSelection = from->selections[num.handleData()]; arx_assert(0 < cutSelection.selected.size()); for(size_t k = 0; k < cutSelection.selected.size(); k++) { inpos = cutSelection.selected[k]; equival[cutSelection.selected[k]] = k; nouvo->vertexlist[k] = from->vertexlist[cutSelection.selected[k]]; nouvo->vertexlist[k].v = from->vertexlist3[cutSelection.selected[k]].v; nouvo->vertexlist[k].v -= ioo->pos; nouvo->vertexlist[k].vert.p = nouvo->vertexlist[k].v; nouvo->vertexlist[k].vert.color = from->vertexlist[k].vert.color; nouvo->vertexlist[k].vert.uv = from->vertexlist[k].vert.uv; nouvo->vertexlist3[k] = nouvo->vertexlist[k]; } size_t count = cutSelection.selected.size(); for(size_t k = 0; k < from->facelist.size(); k++) { if(from->facelist[k].texid == gore) { if( IsNearSelection(from, from->facelist[k].vid[0], num) || IsNearSelection(from, from->facelist[k].vid[1], num) || IsNearSelection(from, from->facelist[k].vid[2], num) ) { for(long j = 0; j < 3; j++) { equival[from->facelist[k].vid[j]] = count; if(count < nouvo->vertexlist.size()) { nouvo->vertexlist[count] = from->vertexlist[from->facelist[k].vid[j]]; nouvo->vertexlist[count].v = from->vertexlist3[from->facelist[k].vid[j]].v; nouvo->vertexlist[count].v -= ioo->pos; nouvo->vertexlist[count].vert.p = nouvo->vertexlist[count].v; nouvo->vertexlist3[count] = nouvo->vertexlist[count]; } else { equival[from->facelist[k].vid[j]] = -1; } count++; } } } } float min = nouvo->vertexlist[0].vert.p.y; long nummm = 0; for(size_t k = 1; k < nouvo->vertexlist.size(); k++) { if(nouvo->vertexlist[k].vert.p.y > min) { min = nouvo->vertexlist[k].vert.p.y; nummm = k; } } nouvo->origin = nummm; nouvo->point0 = nouvo->vertexlist[nouvo->origin].v; for(size_t k = 0; k < nouvo->vertexlist.size(); k++) { nouvo->vertexlist[k].vert.p = nouvo->vertexlist[k].v -= nouvo->point0; nouvo->vertexlist[k].vert.color = Color(255, 255, 255, 255).toRGBA(); } nouvo->point0 = Vec3f_ZERO; nouvo->pbox = NULL; nouvo->pdata = NULL; nouvo->cdata = NULL; nouvo->sdata = NULL; nouvo->ndata = NULL; size_t nfaces = 0; for(size_t k = 0; k < from->facelist.size(); k++) { if( equival[from->facelist[k].vid[0]] != -1 && equival[from->facelist[k].vid[1]] != -1 && equival[from->facelist[k].vid[2]] != -1 ) { nfaces++; } } if(nfaces) { nouvo->facelist.reserve(nfaces); for(size_t k = 0; k < from->facelist.size(); k++) { if( equival[from->facelist[k].vid[0]] != -1 && equival[from->facelist[k].vid[1]] != -1 && equival[from->facelist[k].vid[2]] != -1 ) { EERIE_FACE newface = from->facelist[k]; newface.vid[0] = (unsigned short)equival[from->facelist[k].vid[0]]; newface.vid[1] = (unsigned short)equival[from->facelist[k].vid[1]]; newface.vid[2] = (unsigned short)equival[from->facelist[k].vid[2]]; nouvo->facelist.push_back(newface); } } long gore = -1; for(size_t k = 0; k < from->texturecontainer.size(); k++) { if(from->texturecontainer[k] && boost::contains(from->texturecontainer[k]->m_texName.string(), "gore") ) { gore = k; break; } } for(size_t k = 0; k < nouvo->facelist.size(); k++) { nouvo->facelist[k].facetype &= ~POLY_HIDE; if(nouvo->facelist[k].texid == gore) { nouvo->facelist[k].facetype |= POLY_DOUBLESIDED; } } } free(equival); nouvo->texturecontainer = from->texturecontainer; nouvo->linked.clear(); nouvo->originaltextures = NULL; Entity * io = new Entity("noname", EntityInstance(0)); io->_itemdata = new IO_ITEMDATA(); io->ioflags = IO_ITEM | IO_NOSAVE | IO_MOVABLE; io->script.size = 0; io->script.data = NULL; io->gameFlags |= GFLAG_NO_PHYS_IO_COL; EERIE_COLLISION_Cylinder_Create(io); EERIE_PHYSICS_BOX_Create(nouvo); if(!nouvo->pbox){ delete nouvo; return; } io->infracolor = Color3f::blue * 0.8f; io->collision = COLLIDE_WITH_PLAYER; io->m_icon = NULL; io->scriptload = 1; io->obj = nouvo; io->lastpos = io->initpos = io->pos = ioo->obj->vertexlist3[inpos].v; io->angle = ioo->angle; io->gameFlags = ioo->gameFlags; io->halo = ioo->halo; io->angle.setYaw(Random::getf(340.f, 380.f)); io->angle.setPitch(Random::getf(0.f, 360.f)); io->angle.setRoll(0); io->obj->pbox->active = 1; io->obj->pbox->stopcount = 0; io->velocity = Vec3f_ZERO; io->stopped = 1; Vec3f vector; vector.x = -std::sin(glm::radians(io->angle.getPitch())); vector.y = std::sin(glm::radians(io->angle.getYaw())) * 2.f; vector.z = std::cos(glm::radians(io->angle.getPitch())); vector = glm::normalize(vector); io->rubber = 0.6f; io->no_collide = ioo->index(); io->gameFlags |= GFLAG_GOREEXPLODE; io->animBlend.lastanimtime = arxtime.now_ul(); io->soundtime = 0; io->soundcount = 0; EERIE_PHYSICS_BOX_Launch(io->obj, io->pos, io->angle, vector); }
void ARX_NPC_TryToCutSomething(Entity * target, const Vec3f * pos) { //return; if(!target || !(target->ioflags & IO_NPC)) return; if(target->gameFlags & GFLAG_NOGORE) return; float mindistSqr = std::numeric_limits<float>::max(); ObjSelection numsel = ObjSelection(); long goretex = -1; for(size_t i = 0; i < target->obj->texturecontainer.size(); i++) { if(target->obj->texturecontainer[i] && boost::contains(target->obj->texturecontainer[i]->m_texName.string(), "gore") ) { goretex = i; break; } } for(size_t i = 0; i < target->obj->selections.size(); i++) { ObjSelection sel = ObjSelection(i); if(target->obj->selections[i].selected.size() > 0 && boost::contains(target->obj->selections[i].name, "cut_") ) { DismembermentFlag fll = GetCutFlag(target->obj->selections[i].name); if(IsAlreadyCut(target, fll)) continue; long out = 0; for(size_t ll = 0; ll < target->obj->facelist.size(); ll++) { EERIE_FACE & face = target->obj->facelist[ll]; if(face.texid != goretex) { if( IsInSelection(target->obj, face.vid[0], sel) || IsInSelection(target->obj, face.vid[1], sel) || IsInSelection(target->obj, face.vid[2], sel) ) { if(face.facetype & POLY_HIDE) { out++; } } } } if(out < 3) { float dist = glm::distance2(*pos, target->obj->vertexlist3[target->obj->selections[i].selected[0]].v); if(dist < mindistSqr) { mindistSqr = dist; numsel = sel; } } } } if(numsel == ObjSelection()) return; // Nothing to cut... bool hid = false; if(mindistSqr < square(60)) { // can only cut a close part... DismembermentFlag fl = GetCutFlag( target->obj->selections[numsel.handleData()].name ); if(fl && !(target->_npcdata->cuts & fl)) { target->_npcdata->cuts |= fl; hid = ARX_NPC_ApplyCuts(target); } } if(hid) { ARX_SOUND_PlayCinematic("flesh_critical", false); // TODO why play cinmeatic sound? ARX_NPC_SpawnMember(target, numsel); } }