//------------------------------------------------------------------------------------- PyObject* Proxy::pyGiveClientTo(PyObject* pyOterProxy) { if(this->isDestroyed()) { PyErr_Format(PyExc_AssertionError, "%s: %d is destroyed!\n", scriptName(), id()); PyErr_PrintEx(0); return 0; } if (pyOterProxy == NULL || !PyObject_TypeCheck(pyOterProxy, Proxy::getScriptType())) { PyErr_Format(PyExc_AssertionError, "%s[%d]::giveClientTo: arg1 not is Proxy!\n", scriptName(), id()); PyErr_PrintEx(0); return 0; } // 如果为None 则设置为NULL Proxy* oterProxy = NULL; if(pyOterProxy != Py_None) oterProxy = static_cast<Proxy*>(pyOterProxy); giveClientTo(oterProxy); S_Return; }
//------------------------------------------------------------------------------------- void Proxy::onDefDataChanged(const PropertyDescription* propertyDescription, PyObject* pyData) { uint32 flags = propertyDescription->getFlags(); if((flags & ED_FLAG_BASE_AND_CLIENT) <= 0 || clientMailbox_ == NULL) return; // 创建一个需要广播的模板流 MemoryStream* mstream = MemoryStream::ObjPool().createObject(); propertyDescription->getDataType()->addToStream(mstream, pyData); Mercury::Bundle* pBundle = Mercury::Bundle::ObjPool().createObject(); (*pBundle).newMessage(ClientInterface::onUpdatePropertys); (*pBundle) << id(); if(scriptModule_->usePropertyDescrAlias()) (*pBundle) << propertyDescription->aliasIDAsUint8(); else (*pBundle) << propertyDescription->getUType(); pBundle->append(*mstream); g_privateClientEventHistoryStats.trackEvent(scriptName(), propertyDescription->getName(), pBundle->currMsgLength()); sendToClient(ClientInterface::onUpdatePropertys, pBundle); MemoryStream::ObjPool().reclaimObject(mstream); }
//------------------------------------------------------------------------------------- PyObject* Proxy::pyClientAddr() { if(isDestroyed()) { PyErr_Format(PyExc_AssertionError, "%s: %d is destroyed!\n", scriptName(), id()); PyErr_PrintEx(0); return 0; } PyObject* pyobj = PyTuple_New(2); if(clientMailbox() == NULL || clientMailbox()->getChannel() == NULL || clientMailbox()->getChannel()->pEndPoint() == NULL) { PyTuple_SetItem(pyobj, 0, PyLong_FromLong(0)); PyTuple_SetItem(pyobj, 1, PyLong_FromLong(0)); } else { const Network::Address& addr = clientMailbox()->getChannel()->pEndPoint()->addr(); PyTuple_SetItem(pyobj, 0, PyLong_FromUnsignedLong(addr.ip)); PyTuple_SetItem(pyobj, 1, PyLong_FromUnsignedLong(addr.port)); } return pyobj; }
void Door::onLast() { if (const char *lpcszScript = scriptName("onOpen")) { Console->executef(3, lpcszScript, scriptThis(), getId()); } }
bool LoadInitialModules(PyVis* pyVis) { std::string scriptName("EmbeddedBinding"); std::string scriptNameShorthand("eb"); if(!pyVis->LoadModule(scriptName)) { return false; } PyErr_Print(); // So far this seems to be necessary to use EmbeddedBinding from the // PyRun_SimpleString context, but they are still referencing the same module std::string importToSimple = std::string("import ") + scriptName; PyRun_SimpleString(importToSimple.c_str()); // Same, but now even more convenient! So like "eb.ScriptStep()" std::string importToSimpleShorthand = std::string("import ") + scriptName + std::string(" as ") + scriptNameShorthand; PyRun_SimpleString(importToSimpleShorthand.c_str()); PyRun_SimpleString("import numpy"); // handy, was already loaded above anyway PyObject* scriptDict = pyVis->GetDict(scriptName); PyRun_String("ScriptCreate()", Py_eval_input, pyVis->consoleGlobalContextDict, scriptDict); pyVis->consoleLocalContextDict = scriptDict; PyObject* scriptStep = PyDict_GetItemString(scriptDict, "ScriptStep"); // borrowed ref pyVis->scriptStep = scriptStep; // borrowed ref if(!scriptStep || !PyCallable_Check(scriptStep)) { printf("Error loading python potential step function linkage: no ScriptStep()\n"); PyErr_Print(); return false; } return true; }
void CJavascriptStackTrace::Dump(std::ostream& os) const { v8::HandleScope handle_scope(m_isolate); v8::TryCatch try_catch; std::ostringstream oss; for (int i=0; i<GetFrameCount(); i++) { v8::Handle<v8::StackFrame> frame = GetFrame(i)->Handle(); v8::String::Utf8Value funcName(frame->GetFunctionName()), scriptName(frame->GetScriptName()); os << "\tat "; if (funcName.length()) os << std::string(*funcName, funcName.length()) << " ("; if (frame->IsEval()) { os << "(eval)"; } else { os << std::string(*scriptName, scriptName.length()) << ":" << frame->GetLineNumber() << ":" << frame->GetColumn(); } if (funcName.length()) os << ")"; os << std::endl; } }
//------------------------------------------------------------------------------------- PyObject* Proxy::pyGetTimeSinceHeardFromClient() { if(isDestroyed()) { PyErr_Format(PyExc_AssertionError, "%s: %d is destroyed!\n", scriptName(), id()); PyErr_PrintEx(0); return 0; } return PyFloat_FromDouble(this->getTimeSinceHeardFromClient()); }
//------------------------------------------------------------------------------------- PyObject* Proxy::pyGetRoundTripTime() { if (!hasFlags(ENTITY_FLAGS_DESTROYING) && isDestroyed()) { PyErr_Format(PyExc_AssertionError, "%s: %d is destroyed!\n", scriptName(), id()); PyErr_PrintEx(0); return 0; } return PyFloat_FromDouble(this->getRoundTripTime()); }
//------------------------------------------------------------------------------------- int VolatileInfo::pySetOptimized(PyObject *value) { if (!PyBool_Check(value)) { PyErr_Format(PyExc_AssertionError, "%s: set pitch value is not bool!\n", scriptName()); PyErr_PrintEx(0); return 0; } optimized_ = value == Py_True; return 0; }
//------------------------------------------------------------------------------------- int VolatileInfo::pySetRoll(PyObject *value) { if (!PyFloat_Check(value)) { PyErr_Format(PyExc_AssertionError, "%s: set roll value is not float!\n", scriptName()); PyErr_PrintEx(0); return 0; } roll_ = (float)PyFloat_AsDouble(value); return 0; }
bool Turret::isTargetable (Player *player, float *minDist, float useRange) { if (player && player->getTeam () != getTeam() && player->getVisibleToTeam (getTeam()) && !player->isDead()) { if (const char* script = scriptName("verifyTarget")) { const char* pRet = Console->evaluatef("%s(%d);", script, player->getId()); if (pRet[0] == 'F' || pRet[0] == 'f') return false; } Point3F playerPos = player->getLeadCenter(); float dist = m_distf (getBoxCenter(), playerPos); if (dist < useRange) targetsTracked++; if (dist < *minDist) { TMat3F invMat; getNodeOffset (&invMat, "dummy muzzle", gunNode); invMat.inverse(); m_mul (Point3F (playerPos.x, playerPos.y, playerPos.z), invMat, &playerPos); float ele = elevation (playerPos.x, playerPos.y, playerPos.z); float rotz = rotation (-playerPos.x, -playerPos.y); if (!inDeadZone (rotz, ele)) { SimContainerQuery collisionQuery; collisionQuery.id = getId(); collisionQuery.type = -1; collisionQuery.mask = SimTerrainObjectType | SimInteriorObjectType; collisionQuery.detail = SimContainerQuery::DefaultDetail; collisionQuery.box.fMin = getBoxCenter(); collisionQuery.box.fMax = player->getLeadCenter(); SimCollisionInfo collisionInfo; SimContainer* root = findObject(manager,SimRootContainerId,root); root->findLOS(collisionQuery, &collisionInfo); if (!collisionInfo.object || collisionInfo.object == player) { *minDist = dist; return true; } } } } return false; }
void DumpJSStack() { Local<StackTrace> st = StackTrace::CurrentStackTrace(25); OutputDebugStringA("\n\n--- Javascript Stack ---\n"); for( int i = 0; i < st->GetFrameCount(); i++ ) { Local<StackFrame> sf = st->GetFrame(i); char szOut[8 * 1024]; String::Utf8Value scriptName(sf->GetScriptName()); String::Utf8Value funcName(sf->GetFunctionName()); sprintf(szOut, "%s (%d,%d):%s\n", *scriptName, sf->GetLineNumber(), sf->GetColumn(), *funcName); OutputDebugStringA(szOut); } }
//------------------------------------------------------------------------------------- PyObject* Proxy::pyGetEntitiesEnabled() { if(isDestroyed()) { PyErr_Format(PyExc_AssertionError, "%s: %d is destroyed!\n", scriptName(), id()); PyErr_PrintEx(0); return 0; } if(this->entitiesEnabled()) { Py_RETURN_TRUE; } Py_RETURN_FALSE; }
//------------------------------------------------------------------------------------- PyObject* Proxy::pyHasClient() { if (!hasFlags(ENTITY_FLAGS_DESTROYING) && isDestroyed()) { PyErr_Format(PyExc_AssertionError, "%s: %d is destroyed!\n", scriptName(), id()); PyErr_PrintEx(0); return 0; } if(this->hasClient()) { Py_RETURN_TRUE; } Py_RETURN_FALSE; }
void Player::applyDamage(int type,float value,const Point3F pos, const Point3F& vec,const Point3F& mom,int objectId) { const char* script; if (!isGhost()) if ((script = scriptName("onDamage")) != NULL) { const char* pVert; const char* pQuad; getDamageLocation(pos, pVert, pQuad); Console->evaluatef("%s(%s,%d,%g,\"%g %g %g\",\"%g %g %g\",\"%g %g %g\",%s,%s,%d);", script,scriptThis(),type,value, pos.x,pos.y,pos.z, vec.x,vec.y,vec.z, mom.x,mom.y,mom.z, pVert, pQuad, objectId); } }
void Player::kill () { if (isGhost() || dead) return; dead = true; damageLevel = data->maxDamage; setMaskBits (DamageMask); disableSupressionField(); dieTime = manager->getCurrentTime(); if (const char* script = scriptName("onKilled")) Console->executef(2,script,scriptThis()); type = CorpseObjectType; collisionMask = ServerCorpseCollisionMask; collisionImage.trigger = true; SimMessageEvent::post(this, manager->getCurrentTime() + CorpseTriggerTimeout, CorpseTriggerMsg); jetting = false; }
//------------------------------------------------------------------------------------- void Base::onDefDataChanged(const PropertyDescription* propertyDescription, PyObject* pyData) { if(initing()) return; if(propertyDescription->isPersistent()) setDirty(); uint32 flags = propertyDescription->getFlags(); if((flags & ED_FLAG_BASE_AND_CLIENT) <= 0 || clientMailbox_ == NULL) return; // 创建一个需要广播的模板流 MemoryStream* mstream = MemoryStream::createPoolObject(); propertyDescription->getDataType()->addToStream(mstream, pyData); Network::Bundle* pBundle = Network::Bundle::createPoolObject(); (*pBundle).newMessage(ClientInterface::onUpdatePropertys); (*pBundle) << id(); if(pScriptModule_->usePropertyDescrAlias()) (*pBundle) << propertyDescription->aliasIDAsUint8(); else (*pBundle) << propertyDescription->getUType(); pBundle->append(*mstream); g_privateClientEventHistoryStats.trackEvent(scriptName(), propertyDescription->getName(), pBundle->currMsgLength()); // 按照当前的设计来说,有clientMailbox_必定是proxy // 至于为何跑到base里来和python本身是C语言实现有关 static_cast<Proxy*>(this)->sendToClient(ClientInterface::onUpdatePropertys, pBundle); MemoryStream::reclaimPoolObject(mstream); }
void ProjectPackager::startAudioDecoder(QStringList flacFiles, QStringList wavpackFiles) { // we can't do a oneliner bash script straight out of a QProcess command // line, so we'll have to create a purpose built script and run that QString scriptName("/tmp/rosegarden-audio-decoder-backend"); m_script.setFileName(scriptName); // remove any lingering copy from a previous run if (m_script.exists()) m_script.remove(); if (!m_script.open(QIODevice::WriteOnly | QIODevice::Text)) { puke(tr("<qt><p>Unable to write to temporary backend processing script %1.</p>%2</qt>").arg(scriptName).arg(m_abortText)); return; } QTextStream out(&m_script); out << "# This script was generated by Rosegarden to combine multiple external processing" << endl << "# operations so they could be managed by a single QProcess. If you find this script" << endl << "# it is likely that something has gone terribly wrong. See http://rosegardenmusic.com" << endl; int errorPoint = 1; // The working directory must be the key to why tar is not failing, but // failing to do anything detectable. Let's cut apart m_filename... QFileInfo fi(m_filename); QString dirname = fi.path(); QString basename = QString("%1.%2").arg(fi.baseName()).arg(fi.completeSuffix()); // There were mysterious stupid problems running tar xf in a separate // QProcess step, so screw it, let's just throw it into this script! out << "tar xzf \"" << basename << "\" || exit " << errorPoint++ << endl; // Decode FLAC files QStringList::const_iterator si; for (si = flacFiles.constBegin(); si != flacFiles.constEnd(); ++si) { QString o1 = (*si); // the file strings are things like xxx.wav.rgp.flac // without specifying the output file they will turn into xxx.wav.rgp.wav // thus it is best to specify the output as xxx.wav // // files from new project packages have rg-23324234.flac files, files // from old project packages have rg-2343242.wav.rgp.flac files, so we // want a robust solution to this one... QFileInfo::baseName() should // get it QFileInfo fi(o1); QString o2 = QString("%1/%2.wav").arg(fi.path()).arg(fi.baseName()); // we'll eschew anything fancy or pretty in this disposable script and // just write a command on each line, terminating with an || exit n // which can be used to figure out at which point processing broke, for // cheap and easy error reporting without a lot of fancy stream wiring // // (let's just try escaping spaces &c. with surrounding " and see if // that is good enough) RG_DEBUG << "flad -d " << o1 << " -o " << o2; out << "flac -d \"" << o1 << "\" -o \"" << o2 << "\" && rm \"" << o1 << "\" || exit " << errorPoint << endl; errorPoint++; } // Decode WavPack files for (si = wavpackFiles.constBegin(); si != wavpackFiles.constEnd(); ++si) { QString o = (*si); // NOTE: wvunpack -d means "delete the file if successful" not "decode" out << "wvunpack -d \"" << o << "\" || exit " << errorPoint << endl; errorPoint++; } m_script.close(); // run the assembled script m_process = new QProcess; // set to the working directory extracted from m_filename above, as this is // was apparently the reason why tar always failed to do anything m_process->setWorkingDirectory(dirname); m_process->start("bash", QStringList() << scriptName); connect(m_process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(finishUnpack(int, QProcess::ExitStatus))); // wait up to 30 seconds for process to start m_info->setText(tr("Decoding audio files...")); if (!m_process->waitForStarted()) { puke(tr("<qt>Could not start backend processing script %1.</qt>").arg(scriptName)); return; } }
void ProjectPackager::startAudioEncoder(QStringList files) { m_info->setText(tr("Packing project...")); // (we could do some kind of QProcess monitoring, but I'm feeling lazy at // the moment and this will at least make us look busy while we chew) // go into spinner mode m_progress->setMaximum(0); // we can't do a oneliner bash script straight out of a QProcess command // line, so we'll have to create a purpose built script and run that QString scriptName("/tmp/rosegarden-audio-encoder-backend"); m_script.setFileName(scriptName); // remove any lingering copy from a previous run if (m_script.exists()) m_script.remove(); if (!m_script.open(QIODevice::WriteOnly | QIODevice::Text)) { puke(tr("<qt><p>Unable to write to temporary backend processing script %1.</p>%2</qt>").arg(m_abortText)); return; } // build the script QTextStream out(&m_script); out << "# This script was generated by Rosegarden to combine multiple external processing" << endl << "# operations so they could be managed by a single QProcess. If you find this script" << endl << "# it is likely that something has gone terribly wrong. See http://rosegardenmusic.com" << endl; QStringList::const_iterator si; int errorPoint = 1; for (si = files.constBegin(); si != files.constEnd(); ++si) { QFileInfo fi(*si); QString filename = QString("%1.%2").arg(fi.baseName()).arg(fi.completeSuffix()); QString o = QString("%1/%2").arg(m_packDataDirName).arg(filename); // we'll eschew anything fancy or pretty in this disposable script and // just write a command on each line, terminating with an || exit n // which can be used to figure out at which point processing broke, for // cheap and easy error reporting without a lot of fancy stream wiring out << "wavpack -d \"" << o << "\" || exit " << errorPoint << endl; errorPoint++; } // Throw tar on the ass end of this script and save an extra processing step // // first cheap trick, m_packDataDirName.rg is our boy and we know it QString rgFile = QString("%1.rg").arg(m_packDataDirName); // second cheap trick, don't make a tarball in tmpdir and move it, just // write it at m_filename and shazam, nuke the tmpdir behind us and peace out out << "tar czf \"" << m_filename << "\" " << rgFile.toLocal8Bit() << " " << m_packDataDirName.toLocal8Bit() << "/ || exit " << errorPoint++ << endl; m_script.close(); // run the assembled script m_process = new QProcess; m_process->setWorkingDirectory(m_packTmpDirName); m_process->start("bash", QStringList() << scriptName); connect(m_process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(finishPack(int, QProcess::ExitStatus))); }
void Turret::shoot (bool playerControlled, Player* targetPlayer) { if (data && data->isSustained == false) { if (data && data->projectile.type == -1) { if (!isGhost()) if (const char* script = scriptName("onFire")) Console->executef(2, script, scriptThis()); } else { float energy = getEnergy(); if (waitTime <= manager->getCurrentTime() && data && energy >= data->minGunEnergy && data->projectile.type != -1) { TMat3F muzzleTransform; getMuzzleTransform(0, &muzzleTransform); Projectile* bullet = createProjectile(data->projectile); if (!playerControlled && data->deflection) { static Random random; EulerF angles; muzzleTransform.angles (&angles); angles.x += (random.getFloat() - 0.5) * M_2PI * data->deflection; angles.z += (random.getFloat() - 0.5) * M_2PI * data->deflection; muzzleTransform.set (angles, muzzleTransform.p); } else if (playerControlled) { Point3F start = muzzleTransform.p; muzzleTransform = getEyeTransform (); aimedTransform (&muzzleTransform, start); muzzleTransform.p = start; } bullet->initProjectile (muzzleTransform, Point3F (0, 0, 0), getId()); if (bullet->isTargetable() == true) { if (targetPlayer != NULL) { if (GameBase* mo = targetPlayer->getMountObject()) bullet->setTarget(static_cast<ShapeBase*>(mo)); else bullet->setTarget(targetPlayer); } else if (playerControlled) { ShapeBase* pClosest = NULL; Point3F closeHisPos; float closestVal = -2.0f; SimSet::iterator itr; Point3F lookDir; getEyeTransform().getRow(1, &lookDir); lookDir.normalize(); SimContainerQuery collisionQuery; SimCollisionInfo info; collisionQuery.id = getId(); collisionQuery.type = -1; collisionQuery.mask = Projectile::csm_collisionMask; collisionQuery.detail = SimContainerQuery::DefaultDetail; collisionQuery.box.fMin = getEyeTransform().p; SimContainer* pRoot = (SimContainer*)manager->findObject(SimRootContainerId); SimSet* pSet = dynamic_cast<SimSet*>(manager->findObject(PlayerSetId)); AssertFatal(pSet != NULL, "No player set?"); for (itr = pSet->begin(); itr != pSet->end(); itr++) { Player* pPlayer = dynamic_cast<Player*>(*itr); if (!pPlayer || pPlayer->getVisibleToTeam(getTeam()) == false) continue; collisionQuery.box.fMax = pPlayer->getBoxCenter(); if (pRoot->findLOS(collisionQuery, &info, SimCollisionImageQuery::High) == true) { if (info.object != (SimObject*)pPlayer) continue; } Point3F hisPos = pPlayer->getBoxCenter(); hisPos -= getLinearPosition(); hisPos.normalize(); float prod = m_dot(hisPos, lookDir); if (prod > 0.0f && prod > closestVal) { closestVal = prod; pClosest = pPlayer; closeHisPos = hisPos; } } pSet = dynamic_cast<SimSet*>(manager->findObject(MoveableSetId)); AssertFatal(pSet != NULL, "No moveable set?"); for (itr = pSet->begin(); itr != pSet->end(); itr++) { if (((*itr)->getType() & VehicleObjectType) == 0) continue; ShapeBase* pObject = dynamic_cast<ShapeBase*>(*itr); if (pObject->getVisibleToTeam(getTeam()) == false) continue; collisionQuery.box.fMax = pObject->getBoxCenter(); if (pRoot->findLOS(collisionQuery, &info, SimCollisionImageQuery::High) == true) { if (info.object != (SimObject*)pObject) continue; } Point3F hisPos = pObject->getBoxCenter(); hisPos -= getLinearPosition(); hisPos.normalize(); float prod = m_dot(hisPos, lookDir); if (prod > 0.0f && prod > closestVal) { closestVal = prod; closeHisPos = hisPos; pClosest = pObject; } } // We need to find the current FOV, and take the percentage of // it specified in the .dat file for this turret. Only if the // do product is greater than this, do we allow the target to // be set... // float myFov = (fov / 2.0) * data->targetableFovRatio; float compCos = cos(myFov); if (compCos > 0.996f) // hack for single precision math. It's very compCos = 0.996; // hard to get more precise answers from the dot prod. if (pClosest != NULL && closestVal > compCos) bullet->setTarget(pClosest); } } if (data->maxGunEnergy) { float e; e = energy > data->maxGunEnergy ? data->maxGunEnergy : energy; float pofm = e / float(data->maxGunEnergy); bullet->setEnergy (e, pofm); energy -= e; setEnergy (energy); } SimGroup *grp = NULL; if(SimObject *obj = manager->findObject("MissionCleanup")) grp = dynamic_cast<SimGroup*>(obj); if(!manager->registerObject(bullet)) delete bullet; else { if(grp) grp->addObject(bullet); else manager->addObject(bullet); } waitTime = manager->getCurrentTime() + data->reloadDelay; if (animThread) { setFireThread (); animThread->SetPosition (0.0); } fireCount++; setMaskBits (ShootingMask); } } } else { if (data && data->projectile.type == -1) { if (!isGhost()) if (const char* script = scriptName("onFire")) Console->executef(2, script, scriptThis()); } else { float energy = getEnergy(); if (waitTime <= manager->getCurrentTime() && data && energy >= data->minGunEnergy && data->projectile.type != -1) { TMat3F muzzleTransform; getMuzzleTransform(0, &muzzleTransform); Projectile* bullet = createProjectile(data->projectile); if (!playerControlled && data->deflection) { static Random random; EulerF angles; muzzleTransform.angles (&angles); angles.x += (random.getFloat() - 0.5) * M_2PI * data->deflection; angles.z += (random.getFloat() - 0.5) * M_2PI * data->deflection; muzzleTransform.set (angles, muzzleTransform.p); } else if (playerControlled) { Point3F start = muzzleTransform.p; muzzleTransform = getEyeTransform (); aimedTransform (&muzzleTransform, start); muzzleTransform.p = start; } bullet->initProjectile (muzzleTransform, Point3F (0, 0, 0), getId()); AssertFatal(bullet->isSustained() == true, "Error, must be sustained bullet"); SimGroup *grp = NULL; if(SimObject *obj = manager->findObject("MissionCleanup")) grp = dynamic_cast<SimGroup*>(obj); if(!manager->registerObject(bullet)) delete bullet; else { if(grp) grp->addObject(bullet); else manager->addObject(bullet); } if (animThread) { setFireThread (); animThread->SetPosition (0.0); } fireCount++; setMaskBits (ShootingMask); m_fireState = Firing; m_beganState = wg->currentTime; m_pProjectile = bullet; m_pTarget = targetPlayer; if (m_pTarget) deleteNotify(m_pTarget); } } } }
void Turret::updateMove (PlayerMove *move, float interval) { if (data->isSustained == false) { if (getControlClient() && state != EXTENDED) { if (!isGhost()) extend (interval); } if (state != EXTENDED) move = NULL; float oTR = turretRotation; float oTE = turretElevation; if (move && (!animThread || animThread->getPriority() != -1 || animThread->getPosition() >= 1.0)) { #if 0 float maxSpeed = data->speed * data->speedModifier * interval; float moveFrac = interval * 32; #else float maxSpeed = data->speed * data->speedModifier; float moveFrac = interval * 16; #endif float pitch = m_clamp(move->pitch,-maxSpeed,maxSpeed); float turn = m_clamp(move->turnRot,-maxSpeed,maxSpeed); turretElevation += pitch * moveFrac; turretRotation += turn * moveFrac; wrapElevation (); if (maxElevation != minElevation) { if (turretElevation > maxElevation) turretElevation = maxElevation; if (turretElevation < minElevation) turretElevation = minElevation; } wrapRotation (); if (maxRotation != minRotation) { if (turretRotation > maxRotation) turretRotation = maxRotation; if (turretRotation < minRotation) turretRotation = minRotation; } if (move->trigger) { if (!isGhost ()) shoot (true); } if (move->jumpAction && !isGhost()) { const char *fn = scriptName("jump"); if(fn) Console->executef(2, fn, scriptThis()); } } if (elevationThread && maxElevation != minElevation) elevationThread->SetPosition ((turretElevation - minElevation) / (maxElevation - minElevation)); if (rotationThread) { if (!isEqual (maxRotation, minRotation)) rotationThread->SetPosition ((turretRotation - minRotation) / (maxRotation - minRotation)); else rotationThread->SetPosition (turretRotation / M_2PI); } // this is for the firing anim... if (animThread && state == EXTENDED) animThread->AdvanceTime (interval); // this is for the power anim... if (animThread && isGhost()) { if (state == EXTENDING) extend (interval); else if (state == RETRACTING) retract (interval); } if (!isGhost ()) { // Need to animate on the server to get the // node transforms. image.shape->animate (); if (oTE != turretElevation) setMaskBits (ElevationMask); if (oTR != turretRotation) setMaskBits (TRotationMask); } } else { if (getControlClient() && state != EXTENDED) { if (!isGhost()) extend (interval); } if (state != EXTENDED) move = NULL; float oTR = turretRotation; float oTE = turretElevation; if (move && (!animThread || animThread->getPriority() != -1 || animThread->getPosition() >= 1.0)) { float maxSpeed = data->speed * interval; float pitch = m_clamp(move->pitch,-maxSpeed,maxSpeed); float turn = m_clamp(move->turnRot,-maxSpeed,maxSpeed); float moveFrac = interval * 32; turretElevation += pitch * moveFrac; turretRotation += turn * moveFrac; wrapElevation (); if (maxElevation != minElevation) { if (turretElevation > maxElevation) turretElevation = maxElevation; if (turretElevation < minElevation) turretElevation = minElevation; } wrapRotation (); if (maxRotation != minRotation) { if (turretRotation > maxRotation) turretRotation = maxRotation; if (turretRotation < minRotation) turretRotation = minRotation; } if (move->trigger && m_fireState == Waiting) { if (!isGhost ()) shoot(true, NULL); } else if (!move->trigger && m_fireState == Firing) { if (!isGhost()) unshoot(); } if (move->jumpAction && !isGhost()) { if (m_fireState == Firing) unshoot(); const char *fn = scriptName("jump"); if(fn) Console->executef(2, fn, scriptThis()); } } if (elevationThread && maxElevation != minElevation) elevationThread->SetPosition ((turretElevation - minElevation) / (maxElevation - minElevation)); if (rotationThread) { if (!isEqual (maxRotation, minRotation)) rotationThread->SetPosition ((turretRotation - minRotation) / (maxRotation - minRotation)); else rotationThread->SetPosition (turretRotation / M_2PI); } // this is for the firing anim... if (animThread && state == EXTENDED) animThread->AdvanceTime (interval); // this is for the power anim... if (animThread && isGhost()) { if (state == EXTENDING) extend (interval); else if (state == RETRACTING) retract (interval); } if (!isGhost ()) { // Need to animate on the server to get the // node transforms. image.shape->animate (); if (oTE != turretElevation) setMaskBits (ElevationMask); if (oTR != turretRotation) setMaskBits (TRotationMask); } } }
bool CDialogLoader::ProcessScript(IMScript& script, const string& groupName, TDialogScriptMap& outScriptMap) { #if 0 DiaLOG::Log(DiaLOG::eAlways, "Script: %s with %d lines", script.name, script.lines.size()); for (int i=0; i<script.lines.size(); ++i) { IMScriptLine& line = script.lines[i]; DiaLOG::Log(DiaLOG::eAlways, "actor=%s sound=%s anim=%s facial=%s lookat=%s delay=%f", line.actor,line.sound,line.anim,line.facial,line.lookat,line.delay); } #endif string scriptName (groupName); scriptName+="."; scriptName+=script.name; if (script.lines.empty()) { GameWarning("[DIALOG] CDialogLoader::ProcessScript: DialogScript '%s' has no lines. Discarded.", scriptName.c_str()); return false; } CDialogScript* pScript = new CDialogScript(scriptName); pScript->SetVersionFlags(CDialogScript::VF_EXCEL_BASED, true); bool bDiscard = false; int nLine = 1; std::vector<IMScriptLine>::iterator iter = script.lines.begin(); std::vector<IMScriptLine>::iterator end = script.lines.end(); string animName; for (; iter != end; ++iter, ++nLine) { // process the line const IMScriptLine& line = *iter; int actor = 0; int lookAt = 0; // Actor if (!GetActor(line.actor, actor)) { bDiscard = true; GameWarning("[DIALOG] CDialogLoader::ProcessScript '%s': Line %d: Cannot parse 'Actor' statement. Discarding.", scriptName.c_str(), nLine); break; } if (actor < 1 || actor > CDialogScript::MAX_ACTORS) { bDiscard = true; GameWarning("[DIALOG] CDialogLoader::ProcessScript '%s': Line %d: Actor%d given. Must be within [1..%d]. Discarding.", scriptName.c_str(), nLine, actor, CDialogScript::MAX_ACTORS); break; } bool bUseAGEP = false; bool bUseAGSignal = false; bool bSoundStopsAnim = false; const char* lineAnimName = line.anim; if (CryStringUtils::stristr(lineAnimName, "ex_") == lineAnimName) { // use AG Exact Positioning bUseAGEP = true; lineAnimName+=3; if (*lineAnimName == 0) { bDiscard = true; GameWarning("[DIALOG] CDialogLoader::ProcessScript '%s': Line %d: Invalid AnimName '%s'. Discarding", scriptName.c_str(), nLine, line.anim); break; } } if (lineAnimName[0] == '$') { // use AG Signal bUseAGSignal = true; ++lineAnimName; if (*lineAnimName == 0) { bDiscard = true; GameWarning("[DIALOG] CDialogLoader::ProcessScript '%s': Line %d: Invalid AnimName '%s'. Discarding", scriptName.c_str(), nLine, line.anim); break; } } int animNameLen = strlen(lineAnimName); if (animNameLen >= 2 && lineAnimName[animNameLen-1] == '$') { bSoundStopsAnim = true; --animNameLen; } animName.assign (lineAnimName, animNameLen); // LookAtTarget bool bLookAtGiven = line.lookat && line.lookat[0] != '\0'; bool bLookAtSticky = false; bool bResetLookAt = false; if (bLookAtGiven && CryStringUtils::stristr(line.lookat, "$reset") != 0) { bResetLookAt = true; bLookAtGiven = false; } else if (bLookAtGiven && !GetLookAtActor(line.lookat, lookAt, bLookAtSticky)) { bDiscard = true; GameWarning("[DIALOG] CDialogLoader::ProcessScript: %s Line %d: Cannot parse 'LookAtTarget' statement. Discarding.", scriptName.c_str(), nLine); break; } if (bLookAtGiven && (lookAt < 1 || lookAt > CDialogScript::MAX_ACTORS)) { bDiscard = true; GameWarning("[DIALOG] CDialogLoader::ProcessScript '%s': Line %d: LookAtTarget Actor%d given. Must be within [1..%d]. Discarding.", scriptName.c_str(), nLine, lookAt, CDialogScript::MAX_ACTORS); break; } const char* facialExpression = line.facial.c_str(); bool bResetFacial = false; if (CryStringUtils::stristr(facialExpression, "$reset") != 0) { bResetFacial = true; facialExpression = ""; } const CDialogScript::TActorID actorID = static_cast<CDialogScript::TActorID> (actor-1); const CDialogScript::TActorID lookAtID = lookAt <= 0 ? CDialogScript::NO_ACTOR_ID : static_cast<CDialogScript::TActorID> (lookAt-1); const bool bSuccess = pScript->AddLine(actorID, line.audioID, animName.c_str(), facialExpression, lookAtID, line.delay, line.facialWeight, line.facialFadeTime, bLookAtSticky, bResetFacial, bResetLookAt, bSoundStopsAnim, bUseAGSignal, bUseAGEP); if (!bSuccess) { bDiscard = true; GameWarning("[DIALOG] CDialogLoader::ProcessScript '%s': Cannot add line %d. Discarding", scriptName.c_str(), nLine); break; } } if (bDiscard == false) { // try to complete the script if (pScript->Complete() == true) { // add it to the map std::pair<TDialogScriptMap::iterator, bool> inserted = outScriptMap.insert(TDialogScriptMap::value_type(pScript->GetID(), pScript)); if (inserted.second == false) { bDiscard = true; GameWarning("[DIALOG] CDialogLoader::ProcessScript '%s': Script already defined. Discarded", scriptName.c_str()); } } // completion not successful -> discard else { bDiscard = true; GameWarning("[DIALOG] CDialogLoader::ProcessScript '%s': Cannot complete Script. Discarded.", scriptName.c_str()); } } // discard pScript if (bDiscard) { delete pScript; } return bDiscard == false; }
bool transferSysFiles( Options &options, bool bJustScript ) { Path binpath, libpath; // Under windows, the binary path is usually stored in an envvar. String envpath; if ( ! Sys::_getEnv( "FALCON_BIN_PATH", envpath ) || envpath == "" ) envpath = FALCON_DEFAULT_BIN; binpath.setFullLocation( options.m_sFalconBinDir != "" ? options.m_sFalconBinDir: envpath ); // copy falcon or falrun if ( options.m_sRunner != "" ) binpath.setFilename( options.m_sRunner ); else binpath.setFilename( "falcon.exe" ); // our dlls are in bin, under windows. libpath.setFullLocation( options.m_sFalconLibDir != "" ? options.m_sFalconLibDir : envpath ); if ( ! bJustScript ) { Path tgtpath( options.m_sTargetDir + "/" + options.m_sSystemRoot +"/" ); libpath.setFile( "falcon_engine" ); libpath.setExtension( DllLoader::dllExt() ); tgtpath.setFilename( binpath.getFilename() ); if( ! copyFile( binpath.get(), tgtpath.get() ) ) { warning( "Can't copy system file \"" + binpath.get() + "\" into target path \""+ tgtpath.get()+ "\"" ); // but continue } tgtpath.setFilename( libpath.getFilename() ); if( ! copyFile( libpath.get(), tgtpath.get() ) ) { warning( "Can't copy system file \"" + libpath.get() + "\" into target path \""+ tgtpath.get()+ "\"" ); // but continue } // and now the visual C runtime, if any copyRuntime( binpath, tgtpath ); } // now create the startup script Path mainScriptPath( options.m_sMainScript ); Path scriptPath( options.m_sTargetDir + "/" + mainScriptPath.getFile() + ".bat" ); message( "Creating startup script \"" + scriptPath.get() + "\"" ); FileStream startScript; if( ! startScript.create( scriptPath.get(), (BaseFileStream::t_attributes) 0777 ) ) { error( "Can't create startup script \"" + scriptPath.get() + "\"" ); return false; } startScript.writeString( "@ECHO OFF\r\n" "set OLD_DIR=%CD%\r\n" "set target_dir=%~dp0\r\n" "cd %target_dir%\r\n"); if( bJustScript ) { startScript.writeString( "\"" + binpath.getFilename() + "\" " ); } else { startScript.writeString( " \""+options.m_sSystemRoot + "\\" + binpath.getFilename() + "\" " ); startScript.writeString( " -L \"" + options.m_sSystemRoot +";.\" " ); } // we need to discard the extension, so that the runner decides how to run the program. Path scriptName( options.m_sMainScript ); startScript.writeString( " \"" + scriptName.getFile() +"\" \"%*\"\r\n" ); startScript.writeString( "cd %OLD_DIR%\r\n" ); startScript.flush(); return true; }
//------------------------------------------------------------------------------------- void Proxy::giveClientTo(Proxy* proxy) { if(isDestroyed()) { char err[255]; kbe_snprintf(err, 255, "Proxy[%s]::giveClientTo: %d is destroyed.", scriptName(), id()); PyErr_SetString(PyExc_TypeError, err); PyErr_PrintEx(0); onGiveClientToFailure(); return; } if(clientMailbox_ == NULL || clientMailbox_->getChannel() == NULL) { char err[255]; kbe_snprintf(err, 255, "Proxy[%s]::giveClientTo: no has client.", scriptName()); PyErr_SetString(PyExc_TypeError, err); PyErr_PrintEx(0); onGiveClientToFailure(); return; } Mercury::Channel* lpChannel = clientMailbox_->getChannel(); if(proxy) { if(proxy->isDestroyed()) { char err[255]; kbe_snprintf(err, 255, "Proxy[%s]::giveClientTo: target(%d) is destroyed.", scriptName(), proxy->id()); PyErr_SetString(PyExc_TypeError, err); PyErr_PrintEx(0); onGiveClientToFailure(); return; } if(proxy->id() == this->id()) { char err[255]; kbe_snprintf(err, 255, "Proxy[%s]::giveClientTo: target(%d) is self.", scriptName(), proxy->id()); PyErr_SetString(PyExc_TypeError, err); PyErr_PrintEx(0); onGiveClientToFailure(); return; } EntityMailbox* mb = proxy->clientMailbox(); if(mb != NULL) { ERROR_MSG(boost::format("Proxy::giveClientTo: %1%[%2%] give client to %3%[%4%], %5% has clientMailbox.\n") % scriptName() % id() % proxy->scriptName() % proxy->id() % proxy->scriptName()); onGiveClientToFailure(); return; } if(cellMailbox()) { // 通知cell丢失客户端 Mercury::Bundle* pBundle = Mercury::Bundle::ObjPool().createObject(); (*pBundle).newMessage(CellappInterface::onResetWitness); (*pBundle) << this->id(); sendToCellapp(pBundle); } entitiesEnabled_ = false; clientMailbox()->addr(Mercury::Address::NONE); Py_DECREF(clientMailbox()); proxy->onGiveClientTo(lpChannel); clientMailbox(NULL); addr(Mercury::Address::NONE); if(proxy->clientMailbox() != NULL) { // 通知client销毁当前entity Mercury::Bundle* pBundle = Mercury::Bundle::ObjPool().createObject(); (*pBundle).newMessage(ClientInterface::onEntityDestroyed); (*pBundle) << this->id(); proxy->sendToClient(ClientInterface::onEntityDestroyed, pBundle); //Mercury::Bundle::ObjPool().reclaimObject(pBundle); } } }
//------------------------------------------------------------------------------------- void Proxy::giveClientTo(Proxy* proxy) { if(isDestroyed()) { char err[255]; kbe_snprintf(err, 255, "Proxy[%s]::giveClientTo: %d is destroyed.", scriptName(), id()); PyErr_SetString(PyExc_TypeError, err); PyErr_PrintEx(0); onGiveClientToFailure(); return; } if(clientMailbox_ == NULL || clientMailbox_->getChannel() == NULL) { char err[255]; kbe_snprintf(err, 255, "Proxy[%s]::giveClientTo: no has client.", scriptName()); PyErr_SetString(PyExc_TypeError, err); PyErr_PrintEx(0); onGiveClientToFailure(); return; } Network::Channel* lpChannel = clientMailbox_->getChannel(); if(proxy) { if(proxy->isDestroyed()) { char err[255]; kbe_snprintf(err, 255, "Proxy[%s]::giveClientTo: target(%d) is destroyed.", scriptName(), proxy->id()); PyErr_SetString(PyExc_TypeError, err); PyErr_PrintEx(0); onGiveClientToFailure(); return; } if(proxy->id() == this->id()) { char err[255]; kbe_snprintf(err, 255, "Proxy[%s]::giveClientTo: target(%d) is self.", scriptName(), proxy->id()); PyErr_SetString(PyExc_TypeError, err); PyErr_PrintEx(0); onGiveClientToFailure(); return; } EntityMailbox* mb = proxy->clientMailbox(); if(mb != NULL) { ERROR_MSG(fmt::format("Proxy::giveClientTo: {}[{}] give client to {}[{}], {} has clientMailbox.\n", scriptName(), id(), proxy->scriptName(), proxy->id(), proxy->scriptName())); onGiveClientToFailure(); return; } if(cellMailbox()) { // 当前这个entity如果有cell,说明已经绑定了witness, 那么既然我们将控制权 // 交换给了另一个entity, 这个entity需要解绑定witness。 // 通知cell丢失witness Network::Bundle* pBundle = Network::Bundle::ObjPool().createObject(); (*pBundle).newMessage(CellappInterface::onLoseWitness); (*pBundle) << this->id(); sendToCellapp(pBundle); } // 既然客户端失去对其的控制, 那么通知client销毁这个entity Network::Bundle* pBundle = Network::Bundle::ObjPool().createObject(); (*pBundle).newMessage(ClientInterface::onEntityDestroyed); (*pBundle) << this->id(); sendToClient(ClientInterface::onEntityDestroyed, pBundle); // 将控制权交换 entitiesEnabled_ = false; clientMailbox()->addr(Network::Address::NONE); Py_DECREF(clientMailbox()); proxy->setClientType(this->getClientType()); proxy->setClientDatas(this->getClientDatas()); this->setClientType(UNKNOWN_CLIENT_COMPONENT_TYPE); this->setClientDatas(""); clientMailbox(NULL); proxy->onGiveClientTo(lpChannel); addr(Network::Address::NONE); } }
void CharCreationManager::HandleUploadMessage(MsgEntry* me, Client* client) { Debug1(LOG_NEWCHAR, me->clientnum,"New Character is being created"); psCharUploadMessage upload(me); if(!upload.valid) { Debug2(LOG_NET,me->clientnum,"Received unparsable psUploadMessage from client %u.",me->clientnum); return; } AccountID acctID = client->GetAccountID(); if(!acctID.IsValid()) { Error2("Player tried to upload a character to unknown account %s.", ShowID(acctID)); psCharRejectedMessage reject(me->clientnum); psserver->GetEventManager()->Broadcast(reject.msg, NetBase::BC_FINALPACKET); psserver->RemovePlayer(me->clientnum,"Could not find your account."); return; } // Check to see if the player already has 4 accounts; csString query; query.Format("SELECT id FROM characters WHERE account_id=%d", acctID.Unbox()); Result result(db->Select(query)); if(result.IsValid() && result.Count() >= CHARACTERS_ALLOWED) { psserver->RemovePlayer(me->clientnum,"At your character limit."); return; } csString playerName = upload.name; csString lastName = upload.lastname; playerName = NormalizeCharacterName(playerName); lastName = NormalizeCharacterName(lastName); // Check banned names if(psserver->GetCharManager()->IsBanned(playerName)) { csString error; error.Format("The name %s is banned", playerName.GetData()); psCharRejectedMessage reject(me->clientnum, psCharRejectedMessage::RESERVED_NAME, (char*)error.GetData()); reject.SendMessage(); return; } if(psserver->GetCharManager()->IsBanned(lastName)) { csString error; error.Format("The lastname %s is banned", lastName.GetData()); psCharRejectedMessage reject(me->clientnum, psCharRejectedMessage::RESERVED_NAME, (char*)error.GetData()); reject.SendMessage(); return; } Debug3(LOG_NEWCHAR, me->clientnum,"Got player firstname (%s) and lastname (%s)\n",playerName.GetData(), lastName.GetData()); /////////////////////////////////////////////////////////////// // Check to see if the player name is valid /////////////////////////////////////////////////////////////// if(playerName.Length() == 0 || !FilterName(playerName)) { psCharRejectedMessage reject(me->clientnum, psCharRejectedMessage::NON_LEGAL_NAME, "The name you specifed is not a legal player name."); psserver->GetEventManager()->SendMessage(reject.msg); return; } if(lastName.Length() != 0 && !FilterName(lastName)) { psCharRejectedMessage reject(me->clientnum, psCharRejectedMessage::NON_LEGAL_NAME, "The name you specifed is not a legal lastname."); psserver->GetEventManager()->SendMessage(reject.msg); return; } Debug2(LOG_NEWCHAR, me->clientnum,"Checking player firstname '%s'..\n",playerName.GetData()); /////////////////////////////////////////////////////////////// // Check to see if the character name is unique in 'characters'. /////////////////////////////////////////////////////////////// if(!IsUnique(playerName)) { psCharRejectedMessage reject(me->clientnum, psCharRejectedMessage::NON_UNIQUE_NAME, "The firstname you specifed is not unique."); psserver->GetEventManager()->SendMessage(reject.msg); return; } if(lastName.Length()) { Debug2(LOG_NEWCHAR, me->clientnum,"Checking player lastname '%s'..\n",lastName.GetData()); if(!IsLastNameAvailable(lastName, acctID)) { psCharRejectedMessage reject(me->clientnum, psCharRejectedMessage::NON_UNIQUE_NAME, "The lastname you specifed is not unique."); psserver->GetEventManager()->SendMessage(reject.msg); return; } } /////////////////////////////////////////////////////////////// // Check to see if the character name is on the reserve list. /////////////////////////////////////////////////////////////// int reservedName = IsReserved(playerName, acctID); if(reservedName == NAME_RESERVED) { csString error; error.Format("The name %s is reserved", playerName.GetData()); psCharRejectedMessage reject(me->clientnum, psCharRejectedMessage::RESERVED_NAME, (char*)error.GetData()); psserver->GetEventManager()->SendMessage(reject.msg); return; } csString error; if(!psserver->charCreationManager->Validate(upload, error)) { error.Append(", your creation choices are invalid."); psCharRejectedMessage reject(me->clientnum, psCharRejectedMessage::INVALID_CREATION, (char*)error.GetData()); reject.SendMessage(); return; } /////////////////////////////////////////////////////////////// // Create the psCharacter structure for the player. /////////////////////////////////////////////////////////////// psCharacter* chardata=new psCharacter(); chardata->SetCharType(PSCHARACTER_TYPE_PLAYER); chardata->SetFullName(playerName,lastName); chardata->SetCreationInfo(upload.bio); psRaceInfo* raceinfo=psserver->GetCacheManager()->GetRaceInfoByNameGender(upload.race, (PSCHARACTER_GENDER)upload.gender); if(raceinfo==NULL) { Error3("Invalid race/gender combination on character creation: Race='%d' Gender='%d'", upload.race, upload.gender); psCharRejectedMessage reject(me->clientnum); psserver->GetEventManager()->Broadcast(reject.msg, NetBase::BC_FINALPACKET); psserver->RemovePlayer(me->clientnum,"Player tried to create an invalid race/gender."); delete chardata; return; } chardata->SetRaceInfo(raceinfo); chardata->SetHitPoints(50.0); chardata->GetMaxHP().SetBase(0.0); chardata->GetMaxMana().SetBase(0.0); //range is unused here float x,y,z,yrot,range; const char* sectorname; InstanceID newinstance = DEFAULT_INSTANCE; //get the option entries for tutorial from the server options. Note it's tutorial:variousdata optionEntry* tutorialEntry = psserver->GetCacheManager()->getOptionSafe("tutorial",""); sectorname = tutorialEntry->getOptionSafe("sectorname", "tutorial")->getValue(); psSectorInfo* sectorinfo = psserver->GetCacheManager()->GetSectorInfoByName(sectorname); if(!sectorinfo || PlayerHasFinishedTutorial(acctID, sectorinfo->uid)) { raceinfo->GetStartingLocation(x,y,z,yrot,range,sectorname); sectorinfo = psserver->GetCacheManager()->GetSectorInfoByName(sectorname); //As we aren't going in the tutorial disable the tutorial help messages disable them for(int i = 0; i < TutorialManager::TUTOREVENTTYPE_COUNT; i++) chardata->CompleteHelpEvent(i); } else { // Try tutorial level first. x = tutorialEntry->getOptionSafe("sectorx", "-225.37")->getValueAsDouble(); y = tutorialEntry->getOptionSafe("sectory", "-21.32")->getValueAsDouble(); z = tutorialEntry->getOptionSafe("sectorz", "26.79")->getValueAsDouble(); yrot = tutorialEntry->getOptionSafe("sectoryrot", "-2.04")->getValueAsDouble(); } bool sectorFound = true; if(sectorinfo && EntityManager::GetSingleton().FindSector(sectorinfo->name) == NULL) { Error2("Sector='%s' found but no map file was detected for it. Using NPCroom1", sectorname); sectorinfo = psserver->GetCacheManager()->GetSectorInfoByName("NPCroom1"); if(sectorinfo && EntityManager::GetSingleton().FindSector(sectorinfo->name) == NULL) { Error1("NPCroom1 failed - Critical"); sectorFound = false; } else if(sectorinfo && EntityManager::GetSingleton().FindSector(sectorinfo->name)) { sectorFound = true; } else { sectorFound = false; } } else if(sectorinfo && EntityManager::GetSingleton().FindSector(sectorinfo->name)) { sectorFound = true; } else { sectorFound = false; } if(!sectorFound) { Error2("Unresolvable starting sector='%s'", sectorname); psCharRejectedMessage reject(me->clientnum); psserver->GetEventManager()->Broadcast(reject.msg, NetBase::BC_FINALPACKET); psserver->RemovePlayer(me->clientnum,"No starting Sector."); delete chardata; return; } chardata->SetLocationInWorld(newinstance, sectorinfo, x, y, z, yrot); psTrait* trait; // CPrintf(CON_DEBUG, "Trait: %d\n", upload.selectedFace ); trait = psserver->GetCacheManager()->GetTraitByID(upload.selectedFace); if(trait) chardata->SetTraitForLocation(trait->location, trait); trait = psserver->GetCacheManager()->GetTraitByID(upload.selectedHairStyle); if(trait) chardata->SetTraitForLocation(trait->location, trait); trait = psserver->GetCacheManager()->GetTraitByID(upload.selectedBeardStyle); if(trait) chardata->SetTraitForLocation(trait->location, trait); trait = psserver->GetCacheManager()->GetTraitByID(upload.selectedHairColour); if(trait) chardata->SetTraitForLocation(trait->location, trait); trait = psserver->GetCacheManager()->GetTraitByID(upload.selectedSkinColour); if(trait) chardata->SetTraitForLocation(trait->location, trait); gemActor* actor = new gemActor(gemSupervisor, cacheManager, entityManager, chardata, raceinfo->mesh_name, newinstance, EntityManager::GetSingleton().FindSector(sectorinfo->name), csVector3(x,y,z),yrot, client->GetClientNum()); actor->SetupCharData(); if(!upload.verify) { if(!psServer::CharacterLoader.NewCharacterData(acctID,chardata)) { Error1("Character could not be created."); psCharRejectedMessage reject(me->clientnum); psserver->GetEventManager()->Broadcast(reject.msg, NetBase::BC_FINALPACKET); psserver->RemovePlayer(me->clientnum,"Your character could not be created in the database."); delete chardata; return; } } // Check to see if a path name was set. If so we will use that to generate // the character starting stats and skills. if(upload.path != "None") { // Progression Event name is PATH_PathName csString name("PATH_"); name.Append(upload.path); ProgressionScript* script = psserver->GetProgressionManager()->FindScript(name.GetData()); if(script) { // The script uses the race base character points to calculate starting stats. MathEnvironment env; env.Define("CharPoints", raceinfo->initialCP); env.Define("Actor", actor); script->Run(&env); } } else { //int cpUsage = psserver->charCreationManager->CalculateCPChoice( upload.choices ) + // psserver->charCreationManager->CalculateCPLife(upload.lifeEvents ); for(size_t ci = 0; ci < upload.choices.GetSize(); ci++) { CharCreationManager::CreationChoice* choice = psserver->charCreationManager->FindChoice(upload.choices[ci]); if(choice) { csString name(psserver->charCreationManager->FindChoice(upload.choices[ci])->name.GetData()); Debug3(LOG_NEWCHAR, me->clientnum,"Choice: %s Creation Script: %s", name.GetData(), choice->eventScript.GetData()); MathEnvironment env; env.Define("Actor", actor); if(choice->choiceArea == FATHER_JOB || choice->choiceArea == MOTHER_JOB) { int modifier = (choice->choiceArea == FATHER_JOB) ? upload.fatherMod : upload.motherMod; if(modifier > 3 || modifier < 1) modifier = 1; env.Define("ParentStatus", modifier); } ProgressionScript* script = psserver->GetProgressionManager()->FindScript(choice->eventScript); if(script) script->Run(&env); } else { Debug2(LOG_NEWCHAR, me->clientnum,"Character Choice %d not found\n", upload.choices[ci]); } } for(size_t li = 0; li < upload.lifeEvents.GetSize(); li++) { MathEnvironment env; env.Define("Actor", actor); LifeEventChoiceServer* lifeEvent = psserver->charCreationManager->FindLifeEvent(upload.lifeEvents[li]); if(!lifeEvent) { Error2("No LifeEvent Script found: %d", upload.lifeEvents[li]); continue; } csString scriptName(lifeEvent->eventScript.GetData()); Debug2(LOG_NEWCHAR, me->clientnum, "LifeEvent Script: %s", scriptName.GetDataSafe()); ProgressionScript* script = psserver->GetProgressionManager()->FindScript(scriptName); if(script) script->Run(&env); } } if(!upload.verify) { if(reservedName == NAME_RESERVED_FOR_YOU) { AssignScript(chardata); } // This function recalculates the Max HP, Mana and Stamina of the new character chardata->RecalculateStats(); // Make sure the new player have HP, Mana and Samina that was calculated chardata->SetHitPoints(chardata->GetMaxHP().Base()); chardata->SetMana(chardata->GetMaxMana().Base()); chardata->SetStamina(chardata->GetMaxPStamina().Base(),true); chardata->SetStamina(chardata->GetMaxMStamina().Base(),false); psServer::CharacterLoader.SaveCharacterData(chardata, actor); Debug1(LOG_NEWCHAR,me->clientnum,"Player Creation Complete"); // Remove cached objects to make sure that the client gets a fresh character // list from the database if it logs out and in within 2 minutes. iCachedObject* obj = psserver->GetCacheManager()->RemoveFromCache(psserver->GetCacheManager()->MakeCacheName("list",client->GetAccountID().Unbox())); if(obj) { obj->ProcessCacheTimeout(); obj->DeleteSelf(); } obj = psserver->GetCacheManager()->RemoveFromCache(psserver->GetCacheManager()->MakeCacheName("auth",client->GetAccountID().Unbox())); if(obj) { obj->ProcessCacheTimeout(); obj->DeleteSelf(); } // Here everything is ok client->SetPID(chardata->GetPID()); client->SetName(playerName); psCharApprovedMessage app(me->clientnum); if(app.valid) psserver->GetEventManager()->SendMessage(app.msg); else Bug2("Could not create valid psCharApprovedMessage for client %u.\n",me->clientnum); } else { psCharVerificationMesg mesg(me->clientnum); size_t z; //unfortunately count goes out of valid area so we need to check on charisma for(z = 0; z < psserver->GetCacheManager()->GetSkillAmount(); z++) { unsigned int rank = chardata->Skills().GetSkillRank((PSSKILL) z).Base(); psSkillInfo* info = psserver->GetCacheManager()->GetSkillByID(z); csString name("Not found"); if(info) name.Replace(info->name); if(rank > 0) { if(z >= PSSKILL_AGI && z <= PSSKILL_WILL) { mesg.AddStat(rank, name); } else { mesg.AddSkill(rank, name); } } } mesg.Construct(); mesg.SendMessage(); } delete actor; if(!upload.verify) { // Remove char data from the cache iCachedObject* obj = psserver->GetCacheManager()->RemoveFromCache(psserver->GetCacheManager()->MakeCacheName("char", chardata->GetPID().Unbox())); if(obj) { obj->ProcessCacheTimeout(); obj->DeleteSelf(); } } }