Esempio n. 1
0
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);
}