- Joined
- Jan 9, 2009
- Messages
- 614
- Reaction score
- 152
Got tired of working on this, it's incomplete but I'll release it in its' current state. Note: i included objects.xml which goes into the maps mrs container. if you need help and can't figure it out leave a message here, but i want to see people at least attempt to do it before i spell out how to add it. If anyone finished the collision stuff and can get the wallrun working i would appreciate if it were shared. This not only allows moving platforms and objects but also allows you to load in objects to the map that have bones.
Step 1. download the attached files and add them to your source
Step 2. add these functions to zworld:
step 3. add this to zworld::create at the bottom of the function
step4. replace zgame::getfloor with this:
step 5. add this to zgame::adjustmovediff
step 6. in zmycharacter:ngadget_hanging, find this:
replace with this:
step 7. in zmycharacter:nupdate, find this:
add this below it:
step 8. in zworld::update add this to the top of the function:
step 9. in zworld:raw, add this above m_flags.render:
Step 1. download the attached files and add them to your source
Step 2. add these functions to zworld:
Code:
void ZWorld::LoadWorldObjects()
{
char szMapPath[64] = "";
ZGetCurrMapPath(szMapPath);
char szBuf[256];
sprintf(szBuf, "%s%s/objects.xml", szMapPath, ZGetGameClient()->GetMatchStageSetting()->GetMapName());
MXmlDocument Data;
Data.Create();
MZFile mzf;
if (!mzf.Open(szBuf, g_pFileSystem))
{
return;
}
char* buffer;
buffer = new char[mzf.GetLength() + 1];
mzf.Read(buffer, mzf.GetLength());
buffer[mzf.GetLength()] = 0;
if (!Data.LoadFromMemory(buffer))
{
delete[] buffer;
mlog("Error opening objects file\n");
return;
}
delete[] buffer;
mzf.Close();
MXmlElement rootElement = Data.GetDocumentElement();
int childCount = rootElement.GetChildNodeCount();
for (int i = 0; i < childCount; ++i)
{
MXmlElement child = rootElement.GetChildNode(i);
char TagName[256];
child.GetTagName(TagName);
if (TagName[0] == '#')
{
continue;
}
if (strcmp(TagName, "OBJECT") == 0)
{
WorldObject worldObject;
child.GetAttribute(&worldObject.name, "name");
child.GetAttribute(&worldObject.model, "model");
child.GetAttribute(&worldObject.collradius, "collradius", 0);
child.GetAttribute(&worldObject.collwidth, "collwidth", 0);
child.GetAttribute(&worldObject.collheight, "collheight", 0);
child.GetAttribute(&worldObject.collidable, "collidable", false);
child.GetAttribute(&worldObject.reverseanimation, "reverseanimation", false);
child.GetAttribute(&worldObject.sound, "sound", "");
bool movable = false;
bool usepath = false;
child.GetAttribute(&movable, "moving", false);
child.GetAttribute(&usepath, "usepath", false);
int objectChildCount = child.GetChildNodeCount();
for (int j = 0; j < objectChildCount; ++j)
{
MXmlElement subChild = child.GetChildNode(j);
subChild.GetTagName(TagName);
if (strcmp(TagName, "POSITION") == 0)
{
std::string contents;
subChild.GetContents(&contents);
rvector pos(0, 0, 0);
sscanf(contents.c_str(), "%f,%f,%f", &worldObject.position.x,&worldObject.position.y,&worldObject.position.z);
}
if (strcmp(TagName, "DIRECTION") == 0)
{
std::string contents;
subChild.GetContents(&contents);
rvector pos(0, 1, 0);
sscanf(contents.c_str(), "%f,%f,%f", &worldObject.direction.x, &worldObject.direction.y, &worldObject.direction.z);
}
if (strcmp(TagName, "SPEED") == 0)
{
std::string contents;
subChild.GetContents(&contents);
worldObject.speed = std::stof(contents);
}
if (strcmp(TagName, "ANIMATION") == 0)
{
std::string contents;
subChild.GetContents(&contents);
worldObject.animation = contents;
}
if (strcmp(TagName, "SCALE") == 0)
{
std::string contents;
subChild.GetContents(&contents);
sscanf(contents.c_str(), "%f,%f,%f", &worldObject.scale.x, &worldObject.scale.y, &worldObject.scale.z);
}
if (strcmp(TagName, "COLLISION") == 0)
{
std::string contents;
subChild.GetContents(&contents);
worldObject.collisiontype = static_cast<COLLTYPE>(std::stoi(contents));
}
if (strcmp(TagName, "ENDPOSITION") == 0)
{
std::string contents;
rvector endpos(-1, -1, -1);
subChild.GetContents(&contents);
sscanf(contents.c_str(), "%f,%f,%f", &worldObject.endposition.x, &worldObject.endposition.y, &worldObject.endposition.z);
}
}
std::unique_ptr<ZWorldObject> object;
if (usepath == true || movable == true)
worldObject.objecttype = OBJTYPE::OT_MOVABLE;
if (usepath == true)
object = std::make_unique<ZWorldObject_Navigation>();
else if (movable == true)
object = std::make_unique<ZWorldObject_Movable>();
else
object = std::make_unique<ZWorldObject>();
if (object->InitWithMesh(worldObject))
{
mapObjects.push_back(std::move(object));
}
}
}
}
ZWorldObject* ZWorld::PickWorldObject(rvector& pos, rvector& dir)
{
rvector realfloor = GetBsp()->GetFloor(pos, CHARACTER_RADIUS, CHARACTER_HEIGHT, nullptr);// , fHeight, pimpactplane);
for (auto const& worldObject : mapObjects)
{
if (worldObject->Pick(pos, dir, nullptr))
{
if (realfloor.z >= worldObject->GetPosition().z + worldObject->GetCollHeight())
continue;
return worldObject.get();
}
}
return nullptr;
}
ZWorldObject* ZWorld::CheckWallHang(rvector const& pos, rvector const& dir, bool const& initial)
{
for (auto const& worldObject : mapObjects)
{
if (worldObject->OnCheckWallHang(pos, dir,initial) == true)
{
return worldObject.get();
}
}
return nullptr;
}
ZWorldObject* ZWorld::CheckStandingOnObject(rvector& pos)
{
rvector realfloor = GetBsp()->GetFloor(pos, CHARACTER_RADIUS, CHARACTER_HEIGHT, nullptr);// , fHeight, pimpactplane);
for (auto const& worldObject : mapObjects)
{
if (worldObject->IsStandingOn(pos))
{
if (realfloor.z >= worldObject->GetPosition().z + worldObject->GetCollHeight())
continue;
return worldObject.get();
}
}
return nullptr;
}
rvector ZWorld::GetFloor(rvector& origin, float fRadius, float fHeight, rplane* pimpactplane)
{
rvector realfloor = GetBsp()->GetFloor(origin, fRadius, fHeight, pimpactplane);
ZWorldObject* worldObject = PickWorldObject(origin, rvector(0, 1, 0));
if (worldObject != nullptr && worldObject->IsCollidable())
{
rvector floor = worldObject->GetPosition() + rvector(worldObject->GetCollRadius(), worldObject->GetCollWidth(), worldObject->GetCollHeight());
if (realfloor.z < worldObject->GetPosition().z)
return floor;
}
return realfloor;
}
void ZWorld::RenderMapObjects()
{
for (auto const& mapObjs : mapObjects)
{
mapObjs->Draw();//(0);
}
}
void ZWorld::UpdateMapObjects(float delta)
{
for (auto const& mapObjs : mapObjects)
{
mapObjs->Update(delta);
}
}
step 3. add this to zworld::create at the bottom of the function
Code:
LoadWorldObjects();
step4. replace zgame::getfloor with this:
Code:
rvector ZGame::GetFloor(rvector pos, rplane *pimpactplane, MUID myUID)
{
rvector floor = ZGetGame()->GetWorld()->GetFloor(pos + rvector(0, 0, 120), CHARACTER_RADIUS - 1.1f, 58.f, pimpactplane);
#ifdef ENABLE_CHARACTER_COLLISION
for (auto const& itor : m_ObjectManager)
{
ZObject* pObject = itor.second;
if (pObject == nullptr || pObject == m_pMyCharacter)
continue;
if (pObject->IsCollideable())
// if(!pCharacter->IsDie() && !pCharacter->m_bBlastDrop)
{
rvector diff=pObject->GetPosition()-pos;
diff.z=0;
// ³ªÁß¿¡ radius»ó¼ö°ªÀ¸·Î µÈ°Í ObjectÀÇ ¸â¹öº¯¼ö·Î °íÄ¡ÀÚ
if(Magnitude(diff)<CHARACTER_RADIUS && pos.z>pObject->GetPosition().z)
{
rvector newfloor = pObject->GetPosition()+rvector(0,0,pObject->GetCollHeight());
if(floor.z<newfloor.z)
{
if(m_pMyCharacter->GetUID() == myUID)
{// ³» ij¸¯ÅÍ ¹Ù´Ú À§Ä¡¸¸ ó¸®ÇØÁØ´Ù.
///< Á¡ÇÁ¹ö±× ¶§¹®¿¡ ÀÛ¾÷(ÇÑij¸¯ÅÍÀ§¿¡ ´Ù¸¥ ij¸¯ÅÍ°¡ ¿Ã¶ó °¬À»¶§ ¹Ø¿¡ ij¸¯ÅÍ°¡ Á¡ÇÁ½Ã
///< À§Ä³¸¯ÅÍÀÇ ³ôÀÌ°¡ °»½ÅÀÌ ¾ÈµÇ¸é µÎij¸¯ÅÍ°¡ ¹«ÇÑÁ¤ À§·Î ¿Ã¶ó°¡´Â ¹ö±×)
if(CharacterOverlapCollision(pObject, floor.z, newfloor.z) == false)
continue;
}
floor=newfloor;
if(pimpactplane)
{
rvector up=rvector(0,0,1);
D3DXPlaneFromPointNormal(pimpactplane,&floor,&up);
}
}
}
}
}
#endif
return floor;
}
step 5. add this to zgame::adjustmovediff
Code:
for (auto const& worldObject : GetWorld()->GetWorldObjects())
{
if (worldObject->IsCollidable() == false)
continue;
rvector pos = worldObject->GetPosition();
rvector dir = pObject->GetPosition() + diff - pos;
dir.z = 0;
float fDist = Magnitude(dir);
float objDistance = 0;
if (worldObject->GetCollisionType() == CT_CYLINDER)
objDistance = worldObject->GetCollRadius();
else
objDistance = worldObject->GetCollWidth();
float fCOLLISION_DIST = objDistance + pObject->GetCollRadius();
if (worldObject->GetCollisionType() == CT_CYLINDER)
{
if (fDist < fCOLLISION_DIST && fabs(pos.z - pObject->GetPosition().z) < worldObject->GetCollHeight())
{
if (fDist <= 1.f)
{
pos.x += 1.f;
dir = pObject->GetPosition() - pos;
}
if (DotProduct(dir, diff) < 0) // ´õ °¡±î¿öÁö´Â ¹æÇâÀ̸é
{
Normalize(dir);
rvector newthispos = pos + dir * (fCOLLISION_DIST + 1.f);
rvector newdiff = newthispos - pObject->GetPosition();
diff.x = newdiff.x;
diff.y = newdiff.y;
}
}
}
else
{
if (fDist < fCOLLISION_DIST)// && pObject->GetPosition().z <= worldObject->GetPosition().z + worldObject->GetCollHeight())
{
//if (pObject->GetUID() == ZGetMyUID())
//{
// m_pMyCharacter->Die();
//}
float heightdiff = fabs(pObject->GetPosition().z - pos.z);
if (heightdiff < worldObject->GetCollHeight() && pObject->GetPosition().z < pos.z)
{
if (DotProduct(dir, diff) < 0) // ´õ °¡±î¿öÁö´Â ¹æÇâÀ̸é
{
Normalize(dir);
rvector newthispos = pos + dir * (fCOLLISION_DIST + 1.f);
rvector newdiff = newthispos - pObject->GetPosition();
diff.x = newdiff.x;
diff.y = newdiff.y;
}
}
if (pObject->GetVisualMesh()->GetHeadPosition().z <= worldObject->GetPosition().z)
{
float dist = worldObject->GetPosition().z - pObject->GetVisualMesh()->GetHeadPosition().z;
if (dist < worldObject->GetCollHeight())
{
diff.z -= dist;
}
}
}
}
}
step 6. in zmycharacter:ngadget_hanging, find this:
Code:
RBSPPICKINFO bpi;
bool bPicked = ZGetGame()->GetWorld()->GetBsp()->Pick(pickorigin, dir, &bpi);
if (bPicked && Magnitude(pickorigin - bpi.PickPos) < 100.f)
{
zStatus.m_bHangSuccess = true;
rplane plane = bpi.pInfo->plane;
ZGetEffectManager()->AddLightFragment(bpi.PickPos, rvector(plane.a, plane.b, plane.c));
#ifdef _BIRDSOUND
#else
ZGetSoundEngine()->PlaySoundHangOnWall(GetItems()->GetSelectedWeapon()->GetDesc(), bpi.PickPos);
#endif
SetLastThrower(MUID(0, 0), 0.0f);
}
else
zStatus.m_bHangSuccess = false;
replace with this:
Code:
//Custom: worldobjects. check if player can hang. if they can move them to the proper position and set a hang success
ZWorldObject* worldObject = ZGetGame()->GetWorld()->CheckWallHang(pickorigin, dir,true);
if (worldObject != nullptr)
{
zStatus.m_bHangSuccess = true;
SetPosition(rvector(m_Position.Ref().x, m_Position.Ref().y, GetPosition().z + worldObject->GetLastMoveDiff().z));
ZGetSoundEngine()->PlaySoundHangOnWall(GetItems()->GetSelectedWeapon()->GetDesc(),(rvector)GetPosition() + worldObject->GetLastMoveDiff());
}
else
{
RBSPPICKINFO bpi;
bool bPicked = ZGetGame()->GetWorld()->GetBsp()->Pick(pickorigin, dir, &bpi);
if (bPicked && Magnitude(pickorigin - bpi.PickPos) < 100.f)
{
zStatus.m_bHangSuccess = true;
rplane plane = bpi.pInfo->plane;
ZGetEffectManager()->AddLightFragment(bpi.PickPos, rvector(plane.a, plane.b, plane.c));
#ifdef _BIRDSOUND
#else
ZGetSoundEngine()->PlaySoundHangOnWall(GetItems()->GetSelectedWeapon()->GetDesc(), bpi.PickPos);
#endif
SetLastThrower(MUID(0, 0), 0.0f);
}
else
zStatus.m_bHangSuccess = false;
}
step 7. in zmycharacter:nupdate, find this:
Code:
zStatus.m_bMoving = Magnitude(rvector(GetVelocity().x,GetVelocity().y,0))>.1f;
add this below it:
Code:
/*Custom: worldobjects : if a player is currently picking an object and the heightdiff is less than collision, set landing to true
so walking when the object is going down won't cause acceleration issues*/
ZWorldObject* obje = ZGetGame()->GetWorld()->CheckStandingOnObject(m_Position.Ref());
if (obje != nullptr)
{
if (uStatus.m_bJumpUp == false && uStatus.m_bJumpDown == false)
{
rvector diff = m_Position.Ref();
if (!zStatus.m_bMoving)
{
rvector diff = rvector(obje->GetLastMoveDiff().x, obje->GetLastMoveDiff().y, 0);
Move(diff);
}
SetPosition(rvector(m_Position.Ref().x, m_Position.Ref().y, obje->GetPosition().z + obje->GetCollHeight()));
//m_Position.Ref().z = obje->GetPosition().z + obje->GetCollHeight();
}
}
//Custom: Worldobjects : if player isn't standing on top of the object, attempt to hang. redo later so players can jump from one objec tto another and hang
else
{
obje = ZGetGame()->GetWorld()->CheckWallHang(m_Position.Ref() + rvector(0,0,210), m_Direction);
if (obje != nullptr && (zStatus.m_bHangSuccess == true && zStatus.m_bWallHang == true))
{
rvector diff = rvector(obje->GetLastMoveDiff().x, obje->GetLastMoveDiff().y,0);
Move(diff);
SetPosition(rvector(m_Position.Ref().x, m_Position.Ref().y, m_Position.Ref().z + obje->GetLastMoveDiff().z));
}
}
step 8. in zworld::update add this to the top of the function:
Code:
UpdateMapObjects(fDelta);
step 9. in zworld:raw, add this above m_flags.render:
Code:
RenderMapObjects();
Attachments
Last edited: