void SpawnManager::RemoveNPC(gemObject *obj) { Debug2(LOG_SPAWN,0,"RemoveNPC:%s\n",obj->GetName() ); ServerStatus::mob_deathcount++; PID pid = obj->GetPID(); Notify3(LOG_SPAWN, "Sending NPC %s disconnect msg to %zu clients.\n", ShowID(obj->GetEID()), obj->GetMulticastClients().GetSize()); if (obj->GetCharacterData()==NULL) { Error2("Character data for npc character %s was not found! Entity stays dead.\n", ShowID(pid)); return; } SpawnRule *respawn = NULL; int spawnruleid = obj->GetCharacterData()->NPC_GetSpawnRuleID(); if (spawnruleid) { // Queue for respawn according to rules respawn = rules.Get(spawnruleid, NULL); } if (!respawn) { if (spawnruleid == 0) // spawnruleid 0 is for non-respawning NPCs { Notify2(LOG_SPAWN,"Temporary NPC based on player ID %s has died. Entity stays dead.\n", ShowID(pid)); } else { Error3("Respawn rule for player %s, rule %d was not found! Entity stays dead.\n", ShowID(pid), spawnruleid); } // Remove mesh, etc from engine entityManager->RemoveActor(obj); return; } // Remove mesh, etc from engine entityManager->RemoveActor(obj); int delay = respawn->GetRespawnDelay(); PID newplayer = respawn->CheckSubstitution(pid); psRespawnGameEvent *newevent = new psRespawnGameEvent(this, delay, newplayer, respawn); psserver->GetEventManager()->Push(newevent); Notify3(LOG_SPAWN, "Scheduled NPC %s to be respawned in %.1f seconds", ShowID(newplayer), (float)delay/1000.0); }
TribeNeed* TribeNeedSet::CalculateNeed(NPC * npc) { for (size_t i=0; i < needs.GetSize()-1; i++) { for (size_t j=i+1; j < needs.GetSize(); j++) { if (needs[i]->GetNeedValue(npc) < needs[j]->GetNeedValue(npc)) { TribeNeed *tmp = needs[i]; needs[i] = needs[j]; needs[j] = tmp; } } } csString log; log.Format("Need for %s(%s)",npc->GetName(),ShowID(npc->GetEID())); for (size_t i=0; i < needs.GetSize(); i++) { log.AppendFmt("\n%20s %10.2f -> %s",needs[i]->GetTypeAndName().GetDataSafe(),needs[i]->current_need,needs[i]->GetNeed()->GetTypeAndName().GetDataSafe()); } Debug2(LOG_TRIBES, GetTribe()->GetID(), "%s", log.GetData()); needs[0]->ResetNeed(); return needs[0]; }
void psClientDR::HandleDeadReckon( MsgEntry* me ) { psDRMessage drmsg(me,0,msgstrings,psengine->GetEngine() ); GEMClientActor* gemActor = (GEMClientActor*)celclient->FindObject( drmsg.entityid ); if (!gemActor) { csTicks currenttime = csGetTicks(); if (currenttime - lastquery > 750) { lastquery = currenttime; } Error2("Got DR message for unknown entity %s.", ShowID(drmsg.entityid)); return; } if (!msgstrings) { Error1("msgstrings not received, cannot handle DR"); return; } // Ignore any updates to the main player...psForcePositionMessage handles that. if (gemActor == celclient->GetMainPlayer()) { psengine->GetModeHandler()->SetModeSounds(drmsg.mode); return; } // Set data for this actor gemActor->SetDRData(drmsg); }
EID EntityManager::CreateNPC(psCharacter *chardata, InstanceID instance, csVector3 pos, iSector* sector, float yrot, bool updateProxList, bool alwaysWatching) { if (chardata==NULL) return false; // FIXME: This should be an assert elsewhere. psRaceInfo *raceinfo=chardata->GetRaceInfo(); if (raceinfo==NULL) { CPrintf(CON_ERROR, "NPC ID %u: Character Load returned with NULL raceinfo pointer!\n", ShowID(chardata->GetPID())); delete chardata; return false; } gemNPC *actor = new gemNPC(chardata, raceinfo->mesh_name, instance, sector, pos, yrot, 0); actor->SetAlwaysWatching(alwaysWatching); if ( !actor->IsValid() ) { CPrintf(CON_ERROR, "Error while creating Entity for NPC '%s'\n", ShowID(chardata->GetPID())); delete actor; delete chardata; return false; } // This is required to identify all managed npcs. actor->SetSuperclientID( chardata->GetAccount() ); // Add NPC Dialog plugin if any knowledge areas are defined in db for him. actor->SetupDialog(chardata->GetPID(), true); // Setup prox list and send to anyone who needs him if ( updateProxList ) { actor->UpdateProxList( true ); // CPrintf(CON_NOTIFY,"------> Entity Manager Setting Imperv\n"); psserver->npcmanager->ControlNPC( actor ); } Debug3(LOG_NPC, 0, "Created NPC actor: <%s>[%s] in world", actor->GetName(), ShowID(actor->GetEID())); return actor->GetEID(); }
void psClientDR::HandleStatsUpdate( MsgEntry* me ) { psStatDRMessage statdrmsg(me); GEMClientActor* gemObject = (GEMClientActor*)celclient->FindObject( statdrmsg.entityid ); if (!gemObject) { Error2("Stat request failed because CelClient not ready for %s", ShowID(statdrmsg.entityid)); return; } // Dirty short cut to allways display 0 HP when dead. if (!gemObject->IsAlive() && statdrmsg.hp) { //printf("clientdr 275 dead"); Error1("Server report HP but object is not alive"); statdrmsg.hp = 0; statdrmsg.hp_rate = 0; } // Check if this client actor was updated GEMClientActor* mainActor = celclient->GetMainPlayer(); if (mainActor == gemObject) { gemObject->GetVitalMgr()->HandleDRData(statdrmsg,"Self"); } else { // Publish Vitals data using EntityID csString ID; ID.Append(gemObject->GetEID().Unbox()); gemObject->GetVitalMgr()->HandleDRData(statdrmsg, ID.GetData() ); } //It is not an else if so Target is always published if (psengine->GetCharManager()->GetTarget() == gemObject) gemObject->GetVitalMgr()->HandleDRData(statdrmsg,"Target"); if (mainActor != gemObject && gemObject->IsGroupedWith(celclient->GetMainPlayer()) ) { if (!groupWindow) { // Get the windowMgr pawsWidget* widget = PawsManager::GetSingleton().FindWidget("GroupWindow"); groupWindow = (pawsGroupWindow*)widget; if (!groupWindow) { Error1("Group Window Was Not Found. Bad Error"); return; } } groupWindow->SetStats(gemObject); } }
csString psResumeScriptEvent::ToString() const { csString result; result.Format("Resuming script operation %s",scriptOp->GetName()); if (npc) { result.AppendFmt("for %s (%s)", npc->GetName(), ShowID(npc->GetEID())); } return result; }
EID EntityManager::CreateNPC(PID npcID, bool updateProxList, bool alwaysWatching) { psCharacter *chardata=psServer::CharacterLoader.LoadCharacterData(npcID,false); if (chardata==NULL) { CPrintf(CON_ERROR, "Couldn't load character for NPC %s.", ShowID(npcID)); return 0; } return CreateNPC(chardata, updateProxList, alwaysWatching); }
void Tribe::SendPerception(const char* pcpt, csArray<NPC*> npcs) { Perception perception(pcpt); for(size_t i=0; i<npcs.GetSize(); i++) { NPC* npc = npcs[i]; RDebug(this, 5, "--> Percept npc %s(%s): %s",npc->GetName(),ShowID(npc->GetEID()),perception.ToString(npc).GetDataSafe()); npc->TriggerEvent(&perception); } }
void EntityManager::HandleUserAction(MsgEntry* me, Client *client) { psUserActionMessage actionMsg(me); csString action; if (!actionMsg.valid) { Debug2(LOG_NET,me->clientnum,"Received unparsable psUserActionMessage from client id %u.",me->clientnum); return; } gemObject *object = gem->FindObject(actionMsg.target); if (actionMsg.target.IsValid() && !object) { Debug2(LOG_ANY, me->clientnum, "User action on unknown entity (%s)!", ShowID(actionMsg.target)); return; } client->SetTargetObject(object); // have special tracking for this for fast processing of other messages if (!object) { // TODO: Evaluate if this output is needed. Debug2(LOG_ANY, me->clientnum, "User action on none or unknown object (%s)!", ShowID(actionMsg.target)); return; } // Resolve default behaviour action = actionMsg.action; if (action == "dfltBehavior") { action = object->GetDefaultBehavior(actionMsg.dfltBehaviors); if (action.IsEmpty()) { return; } } if (action == "select" || action == "context") { if (object != NULL) object->SendTargetStatDR(client); } Debug4(LOG_USER,client->GetClientNum(), "User Action: %s %s %s",client->GetName(), (const char *)action, (object)?object->GetName():"None") object->SendBehaviorMessage(action, client->GetActor() ); }
void psDespawnGameEvent::Trigger() { gemObject* object = gem->FindObject(entity); if(!object) { csString status; status.Format("Despawn event triggered for non-existant NPC %s!", ShowID(entity)); psserver->GetLogCSV()->Write(CSV_STATUS, status); Error2("%s", status.GetData()); return; } spawnmanager->RemoveNPC(object); }
void psClientCharManager::ChangeTrait( MsgEntry* me ) { psTraitChangeMessage mesg(me); EID objectID = mesg.target; GEMClientActor *actor = dynamic_cast<GEMClientActor*>(psengine->GetCelClient()->FindObject(objectID)); if (!actor) { Error2("Got trait change for %s, but couldn't find it!", ShowID(objectID)); return; } // Update main object //psengine->BuildAppearance( object->pcmesh->GetMesh(), mesg.string ); actor->CharAppearance()->ApplyTraits(mesg.string); // Update any doll views registered for changes csArray<iPAWSSubscriber*> dolls = PawsManager::GetSingleton().ListSubscribers("sigActorUpdate"); for (size_t i=0; i<dolls.GetSize(); i++) { if (dolls[i] == NULL) continue; pawsObjectView* doll = dynamic_cast<pawsObjectView*>(dolls[i]); if (doll == NULL) continue; if (doll->GetID() == objectID.Unbox()) // This is a doll of the updated object { iMeshWrapper* dollObject = doll->GetObject(); if (dollObject == NULL) { Error2("Cannot update registered doll view with ID %d because it has no object", doll->GetID()); continue; } psCharAppearance* p = doll->GetCharApp(); p->Clone(actor->CharAppearance()); p->SetMesh(dollObject); p->ApplyTraits(mesg.string); } } }
void SpawnManager::HandleLootItem(MsgEntry *me,Client *client) { psLootItemMessage msg(me); // Possible hack here? We are trusting the client to send the right msg.entity? gemObject *object = gem->FindObject(msg.entity); if (!object) { Error3("LootItem Message from %s specified an erroneous entity id: %s.\n", client->GetName(), ShowID(msg.entity)); return; } gemActor *obj = object->GetActorPtr(); if (!obj) { Error3("LootItem Message from %s specified a non-actor entity id: %s.\n", client->GetName(), ShowID(msg.entity)); return; } psCharacter *chr = obj->GetCharacterData(); if (!chr) { Error3("LootItem Message from %s specified a non-character entity id: %s.\n", client->GetName(), ShowID(msg.entity)); return; } // Check the range to the lootable object. if (client->GetActor()->RangeTo(obj) > RANGE_TO_LOOT ) { psserver->SendSystemError(client->GetClientNum(), "Too far away to loot %s.", obj->GetName() ); return; } psItem *item = chr->RemoveLootItem(msg.lootitem); if (!item) { // Take this out because it is just the result of duplicate loot commands due to lag //Warning3(LOG_COMBAT,"LootItem Message from %s specified bad item id of %d.\n",client->GetName(), msg.lootitem); return; } item->SetLoaded(); csRef<PlayerGroup> group = client->GetActor()->GetGroup(); Client *randfriendclient = NULL; if (group.IsValid()) { randfriendclient = obj->GetRandomLootClient(RANGE_TO_LOOT*10); if (!randfriendclient) { Error3("GetRandomLootClient failed for loot msg from %s, object %s.\n", client->GetName(), item->GetName() ); return; } } csString type; Client *looterclient; // Client that gets the item if ( msg.lootaction == msg.LOOT_SELF || !group.IsValid() ) { looterclient = client; type = "Loot Self"; } else { looterclient = randfriendclient; type = "Loot Roll"; } // Ask group member before take if (msg.lootaction == msg.LOOT_SELF && group.IsValid() && client != randfriendclient && obj->HasBeenAttackedBy(randfriendclient->GetActor())) { psserver->SendSystemInfo(client->GetClientNum(), "Asking roll winner %s if you may take the %s...", randfriendclient->GetName(), item->GetName() ); csString request; request.Format("You have won the roll for a %s, but %s wants to take it." " Will you allow this action?", item->GetName(), client->GetName()); // Item will be held in the prompt until answered. PendingLootPrompt *p = new PendingLootPrompt(client, randfriendclient, item, chr, request, cacheManager, gem); psserver->questionmanager->SendQuestion(p); type.Append(" Pending"); } // Continue with normal looting if not prompting else { // Create the loot message csString lootmsg; if (group.IsValid()) lootmsg.Format("%s won the roll and",looterclient->GetName()); else lootmsg.Format("You"); lootmsg.AppendFmt(" looted a %s",item->GetName()); // Attempt to give to looter bool dropped = looterclient->GetActor()->GetCharacterData()->Inventory().AddOrDrop(item); if (!dropped) { lootmsg.Append(", but can't hold anymore"); type.Append(" (dropped)"); } // Send out the loot message psSystemMessage loot(me->clientnum, MSG_LOOT, lootmsg.GetData() ); looterclient->GetActor()->SendGroupMessage(loot.msg); item->Save(false); } // Trigger item removal on every client in the group which has intrest if (group.IsValid()) { for (int i=0; i < (int)group->GetMemberCount(); i++) { int cnum = group->GetMember(i)->GetClientID(); if (obj->IsLootableClient(cnum)) { psLootRemoveMessage rem(cnum,msg.lootitem); rem.SendMessage(); } } } else { psLootRemoveMessage rem(client->GetClientNum(),msg.lootitem); rem.SendMessage(); } psLootEvent evt( chr->GetPID(), chr->GetCharName(), looterclient->GetCharacterData()->GetPID(), looterclient->GetCharacterData()->GetCharName(), item->GetUID(), item->GetName(), item->GetStackCount(), (int)item->GetCurrentStats()->GetQuality(), 0 ); evt.FireEvent(); }
void SpawnManager::Respawn(PID playerID, SpawnRule* spawnRule) { psCharacter *chardata=psServer::CharacterLoader.LoadCharacterData(playerID,false); if (chardata==NULL) { Error2("Character %s to be respawned does not have character data to be loaded!\n", ShowID(playerID)); return; } csVector3 pos; float angle; csString sectorName; iSector* sector = NULL; InstanceID instance; int count = 4; // For random positions we try 4 times before going with the result. // DetermineSpawnLoc will return true if it is a random picked position so for fixed we will fall true // on the first try. while (spawnRule->DetermineSpawnLoc(chardata, pos, angle, sectorName, instance) && spawnRule->GetMinSpawnSpacingDistance() > 0.0 && count-- > 0) { sector = psserver->entitymanager->GetEngine()->GetSectors()->FindByName(sectorName); csArray<gemObject*> nearlist = psserver->entitymanager->GetGEM()->FindNearbyEntities(sector, pos, spawnRule->GetMinSpawnSpacingDistance(), false); if (nearlist.IsEmpty()) { break; // Nothing in the neare list so spawn position is ok. } Debug4(LOG_SPAWN,0,"Spawn position %s is occuplied by %zu entities. %s", toString(pos,sector).GetDataSafe(), nearlist.GetSize(),count>0?" Will Retry":"Last try"); } CS_ASSERT(sector); Debug1(LOG_SPAWN,0,"Position accepted"); Respawn(chardata, instance, pos, angle, sectorName); }
gemNPC* EntityManager::CreateFamiliar (gemActor *owner, PID masterPID) { psCharacter *chardata = owner->GetCharacterData(); PID familiarID, masterFamiliarID; csString familiarname; csVector3 pos; float yrot = 0.0F; iSector *sector; // FIXME: This probably ought to be an assertion. if ( chardata == NULL ) { CPrintf(CON_ERROR, "Couldn't load character for familiar %s.\n", ShowID(owner->GetPID())); return NULL; } masterFamiliarID = masterPID == 0? GetMasterFamiliarID( chardata ) : masterPID; // Change Familiar's Name const char *charname = chardata->GetCharName(); if ( charname[strlen(charname)-1] == 's' ) { familiarname.Format("%s'", charname); } else { familiarname.Format("%s's", charname); } // Adjust Position of Familiar from owners pos owner->GetPosition( pos, yrot, sector ); InstanceID instance = owner->GetInstance(); familiarID = this->CopyNPCFromDatabase( masterFamiliarID, pos.x + 1.5, pos.y, pos.z + 1.5, yrot, sector->QueryObject()->GetName(), instance, familiarname, "Familiar" ); if ( familiarID == 0 ) { CPrintf(CON_ERROR, "CreateFamiliar failed for %s: Could not copy the master NPC %s\n", ShowID(owner->GetPID()), ShowID(masterFamiliarID)); psserver->SendSystemError( owner->GetClientID(), "Could not copy the master NPC familiar." ); return NULL; } // Create Familiar using new ID this->CreateNPC( familiarID , false); //Do not update proxList, we will do that later. gemNPC * npc = GEMSupervisor::GetSingleton().FindNPCEntity( familiarID ); if (npc == NULL) { psserver->SendSystemError( owner->GetClientID(), "Could not find GEM and set its location."); return NULL; } npc->GetCharacterData()->NPC_SetSpawnRuleID( 0 ); npc->SetOwner( owner ); owner->GetClient()->SetFamiliar( npc ); owner->GetCharacterData()->SetFamiliarID( familiarID ); db->Command("INSERT INTO npc_knowledge_areas(player_id, area, priority) VALUES (%d, 'Pet %s 1', '1')", familiarID.Unbox(), npc->GetCharacterData()->GetRaceInfo()->name.GetData()); psServer::CharacterLoader.SaveCharacterData( npc->GetCharacterData(), npc, false ); psserver->npcmanager->ControlNPC( npc ); psserver->npcmanager->CreatePetOwnerSession( owner, npc->GetCharacterData() ); // For now familiars cannot be attacked as they are defenseless npc->GetCharacterData()->SetImperviousToAttack( ALWAYS_IMPERVIOUS ); // Add npc to all nearby clients npc->UpdateProxList( true ); return npc; }
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(); } } }
bool EntityManager::CreatePlayer (Client* client) { psCharacter *chardata=psServer::CharacterLoader.LoadCharacterData(client->GetPID(),true); if (chardata==NULL) { CPrintf(CON_ERROR, "Couldn't load character for %s!\n", ShowID(client->GetPID())); psserver->RemovePlayer (client->GetClientNum(),"Your character data could not be loaded from the database. Please contact tech support about this."); return false; } // FIXME: This should really be an assert in LoadCharacterData or such psRaceInfo *raceinfo=chardata->GetRaceInfo(); if (raceinfo==NULL) { CPrintf(CON_ERROR, "Character load returned with NULL raceinfo pointer for %s!\n", ShowID(client->GetPID())); psserver->RemovePlayer (client->GetClientNum(),"Your character race could not be loaded from the database. Please contact tech support about this."); delete chardata; return false; } csVector3 pos; float yrot; psSectorInfo *sectorinfo; iSector *sector; InstanceID instance; chardata->GetLocationInWorld(instance,sectorinfo,pos.x,pos.y,pos.z,yrot); sector=FindSector(sectorinfo->name); if (sector==NULL) { Error3("Could not resolve sector >%s< for %s.", sectorinfo->name.GetData(), ShowID(client->GetPID())); psserver->RemovePlayer (client->GetClientNum(),"The server could not create your character entity. (Sector not found) Please contact tech support about this."); delete chardata; return false; } gemActor *actor = new gemActor(chardata,raceinfo->mesh_name, instance,sector,pos,yrot, client->GetClientNum()); client->SetActor(actor); if (!actor || !actor->IsValid() ) { Error2("Error while creating gemActor for Character '%s'\n", chardata->GetCharName()); psserver->RemovePlayer (client->GetClientNum(),"The server could not create your character entity. (new gemActor() failed) Please contact tech support about this."); return false; } chardata->LoadActiveSpells(); // These are commented out now because they are handled by psConnectEvent published // Check for buddy list members // usermanager->NotifyBuddies(client, UserManager::LOGGED_ON); // Check for Guild members to notify // usermanager->NotifyGuildBuddies(client, UserManager::LOGGED_ON); // Set default state actor->SetMode(PSCHARACTER_MODE_PEACE); // Add Player to all Super Clients psserver->npcmanager->AddEntity(actor); psSaveCharEvent *saver = new psSaveCharEvent(actor); saver->QueueEvent(); return true; }
EID EntityManager::CreateNPC(psCharacter *chardata, bool updateProxList, bool alwaysWatching) { csVector3 pos; float yrot; psSectorInfo *sectorinfo; iSector *sector; InstanceID instance; chardata->GetLocationInWorld(instance, sectorinfo,pos.x,pos.y,pos.z,yrot); sector = FindSector(sectorinfo->name); if (sector == NULL) { Error3("Could not resolve sector >%s< for NPC %s.", sectorinfo->name.GetData(), ShowID(chardata->GetPID())); delete chardata; return false; } return CreateNPC(chardata, instance, pos, sector, yrot, updateProxList, alwaysWatching); }
int main(void) { uint32_t i, err; DelayInit(); GPIO_QuickInit(HW_GPIOC, 10, kGPIO_Mode_OPP); #ifdef MK22F25612 UART_QuickInit(UART0_RX_PB16_TX_PB17, 115200); #elif MK20D5 UART_QuickInit(UART1_RX_PC03_TX_PC04, 115200); #endif printf("program for Manley\r\n"); swd_io_init(); SWJ_InitDebug(); SWJ_SetTargetState(RESET_HOLD); ShowID(); for(i=0;i<sizeof(buf);i++) { buf[i] = i & 0xFF; } SWJ_WriteMem(0x20000000, buf, sizeof(buf)); memset(buf, 0, sizeof(buf)); SWJ_ReadMem(0x20000000, buf, sizeof(buf)); for(i=0;i<sizeof(buf);i++) { if(buf[i] != (i & 0xFF)) { printf("error buf[%d]:%d should be:%d\r\n", i, buf[i], i); } } printf("mem teset complete\r\n"); SWJ_SetTargetState(RESET_PROGRAM); err = TFlash_UnlockSequence(); printf("TFlash_UnlockSequence %d\r\n", err); SWJ_SetTargetState(RESET_PROGRAM); err = TFlash_Init(&flash); printf("TFlash_Init %d\r\n", err); err = target_flash_program_page(&flash, 0x00000200, (uint8_t*)flash.image, 512); printf("target_flash_program_page %d\r\n", err); while(1) { GPIO_ToggleBit(HW_GPIOC, 10); DelayMs(500); } }
void Tribe::Unbuild(NPC* npc, gemNPCItem* building) { NPCDebug(npc, 6, "Unbuilding building %s",building->GetName()); Asset* buildingAsset = GetAsset(building); if(buildingAsset) { buildingAsset->status = ASSET_STATUS_NOT_USED; buildingAsset->quantity = 0; SaveAsset(buildingAsset); // Check if there is a building spot that need to be downgrades as well csVector3 buildingPos = npc->GetTribe()->GetHomePosition(); buildingPos -= buildingAsset->pos; Asset* buildingSpot = GetNearestAsset(Tribe::ASSET_TYPE_BUILDINGSPOT, buildingAsset->name, Tribe::ASSET_STATUS_CONSTRUCTED, buildingPos, NULL, 5.0, NULL); if(buildingSpot) { buildingSpot->status = Tribe::ASSET_STATUS_NOT_USED; SaveAsset(buildingSpot); // Now the building asset and the spot is freed inform the server npcclient->GetNetworkMgr()->QueueUnbuildCommand(npc->GetActor(), building); } else { Error4("NPC %s(%s) Failed to find building spot for building %s",npc->GetName(),ShowID(npc->GetEID()),building->GetName()); } } else { Error4("NPC %s(%s) Failed to find building asset for building %s",npc->GetName(),ShowID(npc->GetEID()),building->GetName()); } }
bool GMEventManager::RemovePlayerFromGMEvents(PID playerID) { int runningEventIDAsGM; int runningEventID, gmEventID; csArray<int> completedEventIDsAsGM; csArray<int> completedEventIDs; GMEvent* gmEvent; bool eventsFound = false; runningEventID = GetAllGMEventsForPlayer(playerID, completedEventIDs, runningEventIDAsGM, completedEventIDsAsGM); // remove if partaking in an ongoing event if (runningEventID >= 0) { gmEvent = GetGMEventByID(runningEventID); if (gmEvent) { size_t PlayerIndex = GetPlayerFromEvent(playerID, gmEvent); if(PlayerIndex != SIZET_NOT_FOUND) { gmEvent->Player.DeleteIndex(PlayerIndex); eventsFound = true; } } else Error3("Cannot remove player %s from GM Event %d.", ShowID(playerID), runningEventID); } // remove ref's to old completed events csArray<int>::Iterator evIter = completedEventIDs.GetIterator(); while(evIter.HasNext()) { gmEventID = evIter.Next(); gmEvent = GetGMEventByID(gmEventID); if (gmEvent) { size_t PlayerIndex = GetPlayerFromEvent(playerID, gmEvent); if(PlayerIndex != SIZET_NOT_FOUND) { gmEvent->Player.DeleteIndex(PlayerIndex); eventsFound = true; } } else Error3("Cannot remove player %s from GM Event %d.", ShowID(playerID), runningEventID); } // ...and from the DB too if (eventsFound) db->Command("DELETE FROM character_events WHERE player_id = %u", playerID.Unbox()); // if this is a GM thats being deleted, set its GMID to UNDEFINED_GMID. if (runningEventIDAsGM >= 0) { gmEvent = GetGMEventByID(runningEventIDAsGM); if (gmEvent) { gmEvent->gmID = UNDEFINED_GMID; db->Command("UPDATE gm_events SET gm_id = %d WHERE id = %d", UNDEFINED_GMID, gmEvent->id); } else Error3("Cannot remove GM %s from Event %d.", ShowID(playerID), runningEventID); } evIter = completedEventIDsAsGM.GetIterator(); while(evIter.HasNext()) { gmEventID = evIter.Next(); gmEvent = GetGMEventByID(gmEventID); if (gmEvent) { gmEvent->gmID = UNDEFINED_GMID; db->Command("UPDATE gm_events SET gm_id = %d WHERE id = %d", UNDEFINED_GMID, gmEvent->id); } else Error3("Cannot remove GM %s from Event %d.", ShowID(playerID), gmEventID); } return true; }
void Tribe::Advance(csTicks when, EventManager* eventmgr) { int delta = when - lastAdvance; if(delta < 0) // Handle wrappover of tick { delta = 250; // We just set it to the event timer. } lastAdvance = when; // Manage Wealth if(when - lastGrowth > 1000) { float growth; // We need to help tribes that have no members with some resources // so that they can spawn the first entity if(AliveCount() <= 0 && CountResource(wealthResourceName) < reproductionCost) { growth = wealthResourceGrowth; } else if(CountResource(wealthResourceName) < wealthResourceGrowthActiveLimit) { // Some tribes need constant growth in wealth, though capped to a limit // to prevent tribes with no strain on the resources to grow // infinit in wealth growth = wealthResourceGrowthActive; } else { growth = 0; } // Now calculate the growth. Adding what part that wasn't added // the last time this code where run. accWealthGrowth += growth* ((when - lastGrowth)/1000.0); int amount = int(floor(accWealthGrowth)); accWealthGrowth -= amount; if(amount != 0) AddResource(wealthResourceName, amount); lastGrowth = when; } else if(when - lastGrowth < 0) // Handle wrappoer of tick { lastGrowth = when; } // And manage tribe assignments csString perc; int decreaseValue = delta; // Set it to change the scale on recipe wait times // Manage cyclic recipes for(size_t i=0; i<cyclicRecipes.GetSize(); i++) { cyclicRecipes[i].timeLeft -= decreaseValue; if(cyclicRecipes[i].timeLeft <= 0) { // Add the recipe and reset counter RecipeTreeNode* newNode = new RecipeTreeNode(cyclicRecipes[i].recipe, 0); tribalRecipe->AddChild(newNode); newNode->priority = CYCLIC_RECIPE_PRIORITY; cyclicRecipes[i].timeLeft = cyclicRecipes[i].timeTotal; } } // Manage standard recipes for(size_t i=0; i < members.GetSize(); i++) { NPC* npc = members[i]; Behavior* behavior = npc->GetCurrentBehavior(); // For dead npcs just resurrect them if(!npc->IsAlive()) { // Issue the resurrect perception if we have enough // resources perc = "tribe:resurrect"; Perception pcpt(perc); if(AliveCount() == 0 && (CountResource(wealthResourceName) >= 10 * reproductionCost)) { AddResource(wealthResourceName, -10*reproductionCost); npc->TriggerEvent(&pcpt); } else if(CanGrow()) { AddResource(wealthResourceName,-reproductionCost); npc->TriggerEvent(&pcpt); } continue; } // If we have any npcs with no assignments then // we can parse recipes and send them to work if(behavior && strcasecmp(behavior->GetName(),npcIdleBehavior.GetDataSafe())==0) { RDebug(this, 5, "*** Found Idle NPC %s(%s) checking recipes ***", npc->GetName(),ShowID(npc->GetEID())); // Update recipes wait times UpdateRecipeData(decreaseValue); // Get best recipe. (highest level, no wait time) RecipeTreeNode* bestRecipe = tribalRecipe->GetNextRecipe(); if(!bestRecipe) { // Something went wrong... it should never re-parse the tribal recipe // High chances to be a scripting error break; } if(bestRecipe->wait <= 0) { RDebug(this, 5, "Applying recipe %s.", bestRecipe->recipe->GetName().GetDataSafe()); bestRecipe->nextStep = recipeManager->ApplyRecipe( bestRecipe, this, bestRecipe->nextStep); } // If nextStep is -1 => Recipe is Completed if(bestRecipe->nextStep == -1) { // TODO -- Remove TimeStamp csString rName = bestRecipe->recipe->GetName(); if(rName != "do nothing") { RDebug(this, 5, "Recipe %s completed.", rName.GetData()); } tribalRecipe->RemoveChild(bestRecipe->recipe); } // If nextStep is -2, the recipe has unmet requirements else if(bestRecipe->nextStep == -2) { bestRecipe->nextStep = 0; } } } }