bool Manage3DCursor(Entity * io, bool simulate) { arx_assert(io); if(BLOCK_PLAYER_CONTROLS) return false; float ag = player.angle.getYaw(); if(ag > 180) ag = ag - 360; float drop_miny = (float)(g_size.center().y) - g_size.center().y * (ag * (1.f/70)); if(DANAEMouse.y < drop_miny) return false; Anglef temp = Anglef::ZERO; if(io->ioflags & IO_INVERTED) { temp.setYaw(180.f); temp.setPitch(-MAKEANGLE(270.f - io->angle.getPitch() - (player.angle.getPitch() - STARTED_ANGLE))); } else { temp.setPitch(MAKEANGLE(270.f - io->angle.getPitch() - (player.angle.getPitch() - STARTED_ANGLE))); } EERIE_3D_BBOX bbox; for(size_t i = 0; i < io->obj->vertexlist.size(); i++) { bbox.add(io->obj->vertexlist[i].v); } Vec3f mvectx = angleToVectorXZ(player.angle.getPitch() - 90.f); Vec2f mod = Vec2f(Vec2i(DANAEMouse) - g_size.center()) / Vec2f(g_size.center()) * Vec2f(160.f, 220.f); mvectx *= mod.x; Vec3f mvecty(0, mod.y, 0); Vec3f orgn = player.pos; orgn += angleToVector(player.angle) * 50.f; orgn += mvectx; orgn.y += mvecty.y; Vec3f dest = player.pos; dest += angleToVector(player.angle) * 10000.f; dest += mvectx; dest.y += mvecty.y * 5.f; Vec3f pos = orgn; Vec3f movev = glm::normalize(dest - orgn); float lastanything = 0.f; float height = -(bbox.max.y - bbox.min.y); if(height > -30.f) height = -30.f; Vec3f objcenter = bbox.min + (bbox.max - bbox.min) * Vec3f(0.5f); Vec3f collidpos = Vec3f_ZERO; bool collidpos_ok = false; { float maxdist = 0.f; for(size_t i = 0; i < io->obj->vertexlist.size(); i++) { const EERIE_VERTEX & vert = io->obj->vertexlist[i]; float dist = glm::distance(Vec2f(objcenter.x, objcenter.z), Vec2f(vert.v.x, vert.v.z)) - 4.f; maxdist = std::max(maxdist, dist); } if(io->obj->pbox) { Vec2f tmpVert(io->obj->pbox->vert[0].initpos.x, io->obj->pbox->vert[0].initpos.z); for(int i = 1; i < io->obj->pbox->nb_physvert; i++) { const PHYSVERT & physVert = io->obj->pbox->vert[i]; float dist = glm::distance(tmpVert, Vec2f(physVert.initpos.x, physVert.initpos.z)) + 14.f; maxdist = std::max(maxdist, dist); } } Cylinder cyl2; const float inc = 10.f; long iterating = 40; cyl2.height = std::min(-30.f, height); cyl2.radius = glm::clamp(maxdist, 20.f, 150.f); while(iterating > 0) { cyl2.origin = pos + movev * inc + Vec3f(0.f, bbox.max.y, 0.f); float anything = CheckAnythingInCylinder(cyl2, io, CFLAG_JUST_TEST | CFLAG_COLLIDE_NOCOL | CFLAG_NO_NPC_COLLIDE); if(anything < 0.f) { if(iterating == 40) { CANNOT_PUT_IT_HERE = 1; // TODO is this correct ? return true; } iterating = 0; collidpos = cyl2.origin; if(lastanything < 0.f) { pos.y += lastanything; collidpos.y += lastanything; } } else { pos = cyl2.origin; lastanything = anything; } iterating--; } collidpos_ok = iterating == -1; } objcenter = VRotateY(objcenter, temp.getPitch()); collidpos.x -= objcenter.x; collidpos.z -= objcenter.z; pos.x -= objcenter.x; pos.z -= objcenter.z; if(!collidpos_ok) { CANNOT_PUT_IT_HERE = 1; return false; } if(collidpos_ok && closerThan(player.pos, pos, 300.f)) { if(simulate) { ARX_INTERACTIVE_Teleport(io, pos, true); io->gameFlags &= ~GFLAG_NOCOMPUTATION; glm::quat rotation = glm::toQuat(toRotationMatrix(temp)); if(SPECIAL_DRAGINTER_RENDER) { if(glm::abs(lastanything) > glm::abs(height)) { TransformInfo t(collidpos, rotation, io->scale); static const float invisibility = 0.5f; DrawEERIEInter(io->obj, t, io, false, invisibility); } else { TransformInfo t(pos, rotation, io->scale); float invisibility = Cedric_GetInvisibility(io); DrawEERIEInter(io->obj, t, io, false, invisibility); } } } else { if(glm::abs(lastanything) > std::min(glm::abs(height), 12.0f)) { Entity * io = DRAGINTER; ARX_PLAYER_Remove_Invisibility(); io->obj->pbox->active = 1; io->obj->pbox->stopcount = 0; io->pos = collidpos; io->velocity = Vec3f_ZERO; io->stopped = 1; movev.x *= 0.0001f; movev.y = 0.1f; movev.z *= 0.0001f; Vec3f viewvector = movev; Anglef angle = temp; io->soundtime = 0; io->soundcount = 0; EERIE_PHYSICS_BOX_Launch(io->obj, io->pos, angle, viewvector); ARX_SOUND_PlaySFX(SND_WHOOSH, &pos); io->show = SHOW_FLAG_IN_SCENE; Set_DragInter(NULL); } else { ARX_PLAYER_Remove_Invisibility(); ARX_SOUND_PlayInterface(SND_INVSTD); ARX_INTERACTIVE_Teleport(io, pos, true); io->angle.setYaw(temp.getYaw()); io->angle.setPitch(270.f - temp.getPitch()); io->angle.setRoll(temp.getRoll()); io->stopped = 0; io->show = SHOW_FLAG_IN_SCENE; io->obj->pbox->active = 0; Set_DragInter(NULL); } } GRenderer->SetCulling(Renderer::CullNone); return true; } else { CANNOT_PUT_IT_HERE=-1; } return false; }
/*! * \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); }