PyCallArgs::~PyCallArgs() { PySafeDecRef( tuple ); std::map<std::string, PyRep *>::iterator cur, end; cur = byname.begin(); end = byname.end(); for(; cur != end; cur++) PySafeDecRef( cur->second ); }
void SystemBubble::_BubblecastAddBall( SystemEntity* about_who ) { if( m_dynamicEntities.empty() ) { _log( DESTINY__TRACE, "Add Ball: Nobody to receive." ); return; } Buffer* destinyBuffer = new Buffer; //create AddBalls header Destiny::AddBall_header head; head.more = 0; head.sequence = DestinyManager::GetStamp(); destinyBuffer->Append( head ); DoDestiny_AddBalls addballs; addballs.slims = new PyList; //encode destiny binary about_who->EncodeDestiny( *destinyBuffer ); addballs.destiny_binary = new PyBuffer( &destinyBuffer ); SafeDelete( destinyBuffer ); //encode damage state addballs.damages[ about_who->GetID() ] = about_who->MakeDamageState(); //encode SlimItem addballs.slims->AddItem( new PyObject( new PyString( "foo.SlimItem" ), about_who->MakeSlimItem() ) ); //bubblecast the update PyTuple* t = addballs.Encode(); BubblecastDestinyUpdate( &t, "AddBall" ); PySafeDecRef( t ); }
bool PyCachedCall::Decode(PySubStream **in_ss) { PySubStream *ss = *in_ss; //consume *in_ss = NULL; PySafeDecRef( result ); ss->DecodeData(); if(ss->decoded() == NULL) { SysLog::Error("PyCachedCall","Unable to decode initial stream for PyCachedCall"); PyDecRef( ss ); return false; } if(!ss->decoded()->IsDict()) { SysLog::Error("PyCachedCall","Cached call substream does not contain a dict: %s", ss->decoded()->TypeString()); PyDecRef( ss ); return false; } PyDict *po = (PyDict *) ss->decoded(); PyDict::const_iterator cur, end; cur = po->begin(); end = po->end(); for(; cur != end; cur++) { if(!cur->first->IsString()) continue; PyString *key = (PyString *) cur->first; if( key->content() == "lret" ) result = cur->second->Clone(); } PyDecRef( ss ); return(result != NULL); }
void SystemBubble::_SendRemoveBalls( SystemEntity* to_who ) { if( m_entities.empty() ) { _log( DESTINY__TRACE, "Remove Balls: Nothing to send." ); return; } DoDestiny_RemoveBalls remove_balls; std::map<uint32, SystemEntity*>::const_iterator cur, end; cur = m_entities.begin(); end = m_entities.end(); for(; cur != end; ++cur) { if( cur->second->IsVisibleSystemWide() ) continue; //do not remove these from their state! remove_balls.balls.push_back( cur->second->GetID() ); } _log( DESTINY__TRACE, "Remove Balls:" ); remove_balls.Dump( DESTINY__TRACE, " " ); PyTuple* tmp = remove_balls.Encode(); to_who->QueueDestinyUpdate( &tmp ); //may consume, but may not. PySafeDecRef( tmp ); }
PyException& PyException::operator=( const PyException& oth ) { PySafeDecRef( ssException ); ssException = oth.ssException; if( NULL != ssException ) PyIncRef( ssException ); return *this; }
PyResult& PyResult::operator=( const PyResult& oth ) { PySafeDecRef( ssResult ); ssResult = oth.ssResult; if( NULL != ssResult ) PyIncRef( ssResult ); return *this; }
void RamProxyService::_EncodeBillOfMaterials(const std::vector<RequiredItem> &reqItems, double materialMultiplier, double charMaterialMultiplier, uint32 runs, BillOfMaterials &into) { PySafeDecRef( into.extras.lines ); into.extras.lines = new PyList; PySafeDecRef( into.wasteMaterials.lines ); into.wasteMaterials.lines = new PyList; PySafeDecRef( into.rawMaterials.lines ); into.rawMaterials.lines = new PyList; std::vector<RequiredItem>::const_iterator cur, end; cur = reqItems.begin(); end = reqItems.end(); for(; cur != end; cur++) { // if it's skill, insert it into special dict for skills if(cur->isSkill) { into.skills[cur->typeID] = new PyInt(cur->quantity); continue; } // otherwise, make line for material list MaterialList_Line line; line.requiredTypeID = cur->typeID; line.quantity = static_cast<int32>(ceil(cur->quantity * materialMultiplier * runs)); line.damagePerJob = cur->damagePerJob; line.isSkillCheck = false; // no idea what is this for line.requiresHP = false; // no idea what is this for // and this is thing I'm not sure about ... if I understood it well, "Extra material" is everything not fully consumed, // "Raw material" is everything fully consumed and "Waste Material" is amount of material wasted ... if(line.damagePerJob < 1.0) { into.extras.lines->AddItem( line.Encode() ); } else { // if there are losses, make line for waste material list if(charMaterialMultiplier > 1.0) { MaterialList_Line wastage( line ); // simply copy origial line ... wastage.quantity = static_cast<int32>(ceil(wastage.quantity * (charMaterialMultiplier - 1.0))); // ... and calculate proper quantity into.wasteMaterials.lines->AddItem( wastage.Encode() ); } into.rawMaterials.lines->AddItem( line.Encode() ); } } }
void SystemBubble::_SendAddBalls( SystemEntity* to_who ) { if( m_entities.empty() ) { _log( DESTINY__TRACE, "Add Balls: Nothing to send." ); return; } Buffer* destinyBuffer = new Buffer; Destiny::AddBall_header head; head.packet_type = 0; head.sequence = DestinyManager::GetStamp(); destinyBuffer->Append( head ); DoDestiny_AddBalls addballs; addballs.slims = new PyList; std::map<uint32, SystemEntity*>::const_iterator cur, end; cur = m_entities.begin(); end = m_entities.end(); for(; cur != end; ++cur) { if( cur->second->IsVisibleSystemWide() ) continue; //it is already in their destiny state //damageState addballs.damages[ cur->second->GetID() ] = cur->second->MakeDamageState(); //slim item addballs.slims->AddItem( new PyObject( "foo.SlimItem", cur->second->MakeSlimItem() ) ); //append the destiny binary data... cur->second->EncodeDestiny( *destinyBuffer ); } addballs.destiny_binary = new PyBuffer( &destinyBuffer ); SafeDelete( destinyBuffer ); _log( DESTINY__TRACE, "Add Balls:" ); addballs.Dump( DESTINY__TRACE, " " ); _log( DESTINY__TRACE, " Ball Binary:" ); _hex( DESTINY__TRACE, &( addballs.destiny_binary->content() )[0], addballs.destiny_binary->content().size() ); _log( DESTINY__TRACE, " Ball Decoded:" ); Destiny::DumpUpdate( DESTINY__TRACE, &( addballs.destiny_binary->content() )[0], addballs.destiny_binary->content().size() ); PyTuple* t = addballs.Encode(); to_who->QueueDestinyUpdate( &t ); //may consume, but may not. PySafeDecRef( t ); }
bool InventoryItem::Populate( Rsp_CommonGetInfo_Entry& result ) { //itemID: result.itemID = itemID(); //invItem: PySafeDecRef( result.invItem ); result.invItem = GetItemRow(); //hacky, but it doesn't really hurt anything. if( GetAttribute(AttrIsOnline).get_int() != 0 ) { //there is an effect that goes along with this. We should //probably be properly tracking the effect due to some // timer things, but for now, were hacking it. EntityEffectState es; es.env_itemID = itemID(); es.env_charID = ownerID(); //may not be quite right... es.env_shipID = locationID(); es.env_target = locationID(); //this is what they do. es.env_other = new PyNone; es.env_effectID = effectOnline; es.startTime = Win32TimeNow() - Win32Time_Hour; //act like it happened an hour ago es.duration = INT_MAX; es.repeat = 0; es.randomSeed = new PyNone; result.activeEffects[es.env_effectID] = es.Encode(); } //activeEffects: //result..activeEffects[id] = List[11]; //attributes: AttributeMap::AttrMapItr itr = mAttributeMap.begin(); AttributeMap::AttrMapItr itr_end = mAttributeMap.end(); for (; itr != itr_end; itr++) { result.attributes[(*itr).first] = (*itr).second.GetPyObject(); } //no idea what time this is supposed to be result.time = Win32TimeNow(); return true; }
//NOTE: duplicated from module manager code. They should share some day! void NPCAIMgr::_SendWeaponEffect( const char*effect, SystemEntity *target ) { DoDestiny_OnSpecialFX13 sfx; sfx.entityID = m_npc->Item()->itemID(); sfx.moduleID = m_npc->Item()->itemID(); sfx.moduleTypeID = m_npc->Item()->typeID(); sfx.targetID = target->GetID(); sfx.otherTypeID = target->Item()->typeID(); sfx.effect_type = effect; sfx.isOffensive = 1; sfx.start = 1; sfx.active = 1; //omit these for now, setting up the repeat might be a network optimization, but we dont need it right now. //sfx.duration_ms = 1960; //no idea... sfx.duration_ms = m_npc->Item()->speed(); sfx.repeat = 1; sfx.startTime = Win32TimeNow(); PyTuple* up = sfx.Encode(); m_npc->Destiny()->SendSingleDestinyUpdate( &up ); //consumed PySafeDecRef( up ); }
void TargetManager::QueueTBDestinyUpdate( PyTuple** up_in ) const { PyTuple* up = *up_in; *up_in = NULL; //could optimize out one of the Clones in here... PyTuple* up_dup = NULL; std::map<SystemEntity*, TargetedByEntry*>::const_iterator cur, end; cur = m_targetedBy.begin(); end = m_targetedBy.end(); for(; cur != end; ++cur) { if( NULL == up_dup ) up_dup = new PyTuple( *up ); cur->first->QueueDestinyUpdate( &up_dup ); //they may not have consumed it (NPCs for example), so dont re-dup it in that case. } PySafeDecRef( up_dup ); PyDecRef( up ); }
PyResult Command_pop( Client* who, CommandDB* db, PyServiceMgr* services, const Seperator& args ) { if( 4 != args.argCount() ) throw PyException( MakeCustomError( "Correct Usage: /pop [message type] [key] [text]" ) ); //CustomNotify: notify //ServerMessage: msg //CustomError: error const std::string& msgType = args.arg( 1 ); const std::string& key = args.arg( 2 ); const std::string& text = args.arg( 3 ); Notify_OnRemoteMessage n; n.msgType = msgType; n.args[ key ] = new PyString( text ); PyTuple* t = n.Encode(); who->SendNotification( "OnRemoteMessage", "charid", &t ); PySafeDecRef( t ); return new PyString( "Message sent." ); }
//send a destiny event to everybody in the bubble. //assume that static entities are also not interested in destiny updates. void SystemBubble::BubblecastDestinyEvent( PyTuple** payload, const char* desc ) const { PyTuple* up = *payload; *payload = NULL; //could optimize out one of the Clones in here... PyTuple* up_dup = NULL; std::set<SystemEntity *>::const_iterator cur, end, tmp; cur = m_dynamicEntities.begin(); end = m_dynamicEntities.end(); for(; cur != end; ++cur) { if( NULL == up_dup ) up_dup = new PyTuple( *up ); _log( DESTINY__BUBBLE_TRACE, "Bubblecast %s event to %s (%u)", desc, (*cur)->GetName(), (*cur)->GetID() ); (*cur)->QueueDestinyEvent( &up_dup ); //they may not have consumed it (NPCs for example), so dont re-dup it in that case. } PySafeDecRef( up_dup ); PyDecRef( up ); }
bool PyPacket::Decode(PyRep **in_packet) { PyRep *packet = *in_packet; //consume *in_packet = NULL; PySafeDecRef(payload); PySafeDecRef(named_payload); if(packet->IsChecksumedStream()) { PyChecksumedStream* cs = packet->AsChecksumedStream(); //TODO: check cs->checksum packet = cs->stream(); PyIncRef( packet ); PyDecRef( cs ); } //Dragon nuance... it gets wrapped again if(packet->IsSubStream()) { PySubStream* ss = packet->AsSubStream(); ss->DecodeData(); if(ss->decoded() == NULL) { codelog(NET__PACKET_ERROR, "failed: unable to decode initial packet substream."); PyDecRef(packet); return false; } packet = ss->decoded(); PyIncRef( packet ); PyDecRef( ss ); } if(!packet->IsObject()) { codelog(NET__PACKET_ERROR, "failed: packet body is not an 'Object': %s", packet->TypeString()); PyDecRef(packet); return false; } PyObject *packeto = (PyObject *) packet; type_string = packeto->type()->content(); if(!packeto->arguments()->IsTuple()) { codelog(NET__PACKET_ERROR, "failed: packet body does not contain a tuple"); PyDecRef(packet); return false; } PyTuple *tuple = (PyTuple *) packeto->arguments(); if(tuple->items.size() != 7) { codelog(NET__PACKET_ERROR, "failed: packet body does not contain a tuple of length 7"); PyDecRef(packet); return false; } if(!tuple->items[0]->IsInt()) { codelog(NET__PACKET_ERROR, "failed: First main tuple element is not an integer"); PyDecRef(packet); return false; } PyInt *typer = (PyInt *) tuple->items[0]; switch(typer->value()) { case AUTHENTICATION_REQ: case AUTHENTICATION_RSP: case IDENTIFICATION_REQ: case IDENTIFICATION_RSP: case CALL_REQ: case CALL_RSP: case TRANSPORTCLOSED: case RESOLVE_REQ: case RESOLVE_RSP: case NOTIFICATION: case ERRORRESPONSE: case SESSIONCHANGENOTIFICATION: case SESSIONINITIALSTATENOTIFICATION: case PING_REQ: case PING_RSP: type = (MACHONETMSG_TYPE) typer->value(); break; default: codelog(NET__PACKET_ERROR, "failed: Unknown message type %"PRIu64, typer->value()); PyDecRef(packet); return false; break; } //source address if(!source.Decode(tuple->items[1])) { //error printed in decoder PyDecRef(packet); return false; } //dest address if(!dest.Decode(tuple->items[2])) { //error printed in decoder PyDecRef(packet); return false; } if(tuple->items[3]->IsInt()) { PyInt *i = (PyInt *) tuple->items[3]; userid = i->value(); } else if(tuple->items[3]->IsNone()) { userid = 0; } else { codelog(NET__PACKET_ERROR, "failed: User ID has invalid type"); PyDecRef(packet); return false; } //payload if(!(tuple->items[4]->IsBuffer() || tuple->items[4]->IsTuple())) { codelog(NET__PACKET_ERROR, "failed: Fifth main tuple element is not a tuple"); PyDecRef(packet); return false; } payload = (PyTuple *) tuple->items[4]; tuple->items[4] = NULL; //we keep this one //options dict if(tuple->items[5]->IsNone()) { named_payload = NULL; } else if(tuple->items[5]->IsDict()) { named_payload = (PyDict *) tuple->items[5]; tuple->items[5] = NULL; //we keep this too. } else { codelog(NET__PACKET_ERROR, "failed: Sixth main tuple element is not a dict"); PyDecRef(packet); return false; } PyDecRef(packet); return true; }
PyCachedCall::~PyCachedCall() { PySafeDecRef( result ); }
bool PyCachedObjectDecoder::Decode(PySubStream **in_ss) { PySubStream *ss = *in_ss; //consume *in_ss = NULL; PySafeDecRef( cache ); PySafeDecRef( objectID ); ss->DecodeData(); if(ss->decoded() == NULL) { sLog.Error("PyCachedObjectDecoder","Unable to decode initial stream for PycachedObject"); PyDecRef( ss ); return false; } if(!ss->decoded()->IsObject()) { sLog.Error("PyCachedObjectDecoder","Cache substream does not contain an object: %s", ss->decoded()->TypeString()); PyDecRef( ss ); return false; } PyObject *po = (PyObject *) ss->decoded(); //TODO: could check type string, dont care... (should be objectCaching.CachedObject) if(!po->arguments()->IsTuple()) { sLog.Error("PyCachedObjectDecoder","Cache object's args is not a tuple: %s", po->arguments()->TypeString()); PyDecRef( ss ); return false; } PyTuple *args = (PyTuple *) po->arguments(); if(args->items.size() != 7) { sLog.Error("PyCachedObjectDecoder","Cache object's args tuple has %lu elements instead of 7", args->items.size()); PyDecRef( ss ); return false; } if(!args->items[0]->IsTuple()) { sLog.Error("PyCachedObjectDecoder","Cache object's arg %d is not a Tuple: %s", 0, args->items[0]->TypeString()); PyDecRef( ss ); return false; } //ignore unknown [1] /*if(!args->items[1]->IsInt()) { _log(CLIENT__ERROR, "Cache object's arg %d is not a None: %s", 1, args->items[1]->TypeString()); PyDecRef( ss ); return false; }*/ if(!args->items[2]->IsInt()) { sLog.Error("PyCachedObjectDecoder","Cache object's arg %d is not an Integer: %s", 2, args->items[2]->TypeString()); PyDecRef( ss ); return false; } if(!args->items[3]->IsInt()) { sLog.Error("PyCachedObjectDecoder","Cache object's arg %d is not an Integer: %s", 3, args->items[3]->TypeString()); PyDecRef( ss ); return false; } if(!args->items[5]->IsInt()) { sLog.Error("PyCachedObjectDecoder","Cache object's arg %d is not a : %s", 5, args->items[5]->TypeString()); PyDecRef( ss ); return false; } PyTuple *objVt = (PyTuple *) args->items[0]; if(!objVt->items[0]->IsInt()) { sLog.Error("PyCachedObjectDecoder","Cache object's version tuple %d is not an Integer: %s", 0, objVt->items[0]->TypeString()); PyDecRef( ss ); return false; } if(!objVt->items[1]->IsInt()) { sLog.Error("PyCachedObjectDecoder","Cache object's version tuple %d is not an Integer: %s", 1, objVt->items[1]->TypeString()); PyDecRef( ss ); return false; } PyInt *nodeidr = (PyInt *) args->items[2]; PyInt *sharedr = (PyInt *) args->items[3]; PyInt *compressedr = (PyInt *) args->items[5]; PyInt *timer = (PyInt *) objVt->items[0]; PyInt *versionr = (PyInt *) objVt->items[1]; timestamp = timer->value(); version = versionr->value(); nodeID = nodeidr->value(); shared = ( sharedr->value() != 0 ); compressed = ( compressedr->value() != 0 ); //content (do this as the last thing, since its the heavy lifting): if(args->items[4]->IsSubStream()) { cache = (PySubStream *) args->items[4]; //take it args->items[4] = NULL; } else if(args->items[4]->IsBuffer()) { //this is a data buffer, likely compressed. PyBuffer* buf = args->items[4]->AsBuffer(); PyIncRef( buf ); cache = new PySubStream( buf ); } else if(args->items[4]->IsString()) { //this is a data buffer, likely compressed, not sure why it comes through as a string... PyString* str = args->items[4]->AsString(); cache = new PySubStream( new PyBuffer( *str ) ); } else { sLog.Error("PyCachedObjectMgr", "Cache object's arg %d is not a substream or buffer: %s", 4, args->items[4]->TypeString()); PyDecRef( ss ); return false; } objectID = args->items[6]; PyIncRef(objectID); PyDecRef( ss ); return true; }
PyCachedObject::~PyCachedObject() { PySafeDecRef( cache ); PySafeDecRef( objectID ); }
PyCachedObjectDecoder::~PyCachedObjectDecoder() { PySafeDecRef( cache ); PySafeDecRef( objectID ); }
bool EVENotificationStream::Decode(const std::string &pkt_type, const std::string ¬ify_type, PyTuple *&in_payload) { PyTuple *payload = in_payload; //consume in_payload = NULL; PySafeDecRef(args); args = NULL; if(pkt_type != "macho.Notification") { codelog(NET__PACKET_ERROR, "notification payload has unknown string type %s", pkt_type.c_str()); PyDecRef(payload); return false; } //decode payload tuple if(payload->items.size() != 2) { codelog(NET__PACKET_ERROR, "invalid tuple length %lu", payload->items.size()); PyDecRef(payload); return false; } if(!payload->items[0]->IsTuple()) { codelog(NET__PACKET_ERROR, "non-tuple payload[0]"); PyDecRef(payload); return false; } PyTuple *payload2 = (PyTuple *) payload->items[0]; if(payload2->items.size() != 2) { codelog(NET__PACKET_ERROR, "invalid tuple2 length %lu", payload2->items.size()); PyDecRef(payload); return false; } //decode inner payload tuple //ignore tuple 0, it should be an int, dont know what it is if(!payload2->items[1]->IsSubStream()) { codelog(NET__PACKET_ERROR, "non-substream type"); PyDecRef(payload); return false; } PySubStream *ss = (PySubStream *) payload2->items[1]; ss->DecodeData(); if(ss->decoded() == NULL) { codelog(NET__PACKET_ERROR, "Unable to decode call stream"); PyDecRef(payload); return false; } if(!ss->decoded()->IsTuple()) { codelog(NET__PACKET_ERROR, "packet body does not contain a tuple"); PyDecRef(payload); return false; } PyTuple *robjt = (PyTuple *) ss->decoded(); if(robjt->items.size() != 2) { codelog(NET__PACKET_ERROR, "packet body has %lu elements, expected %d", robjt->items.size(), 2); PyDecRef(payload); return false; } //parse first tuple element, remote object if(robjt->items[0]->IsInt()) { PyInt *tuple0 = (PyInt *) robjt->items[0]; remoteObject = tuple0->value(); remoteObjectStr = ""; } else if(robjt->items[0]->IsString()) { PyString *tuple0 = (PyString *) robjt->items[0]; remoteObject = 0; remoteObjectStr = tuple0->content(); } else { codelog(NET__PACKET_ERROR, "main tuple[0] has invalid type %s", robjt->items[0]->TypeString()); _log(NET__PACKET_ERROR, " in:"); payload->Dump( NET__PACKET_ERROR, "" ); PyDecRef(payload); return false; } if(!robjt->items[1]->IsTuple()) { codelog(NET__PACKET_ERROR, "main tuple[1] has non-tuple type %s", robjt->items[0]->TypeString()); _log(NET__PACKET_ERROR, " it is:"); payload->Dump( NET__PACKET_ERROR, "" ); PyDecRef(payload); return false; } PyTuple *subt = (PyTuple *) robjt->items[1]; if(subt->items.size() != 2) { codelog(NET__PACKET_ERROR, "packet body has %lu elements, expected %d", subt->items.size(), 2); PyDecRef(payload); return false; } //parse first tuple element, remote object if(subt->items[0]->IsInt()) { //PyInt *tuple0 = (PyInt *) maint->items[0]; //no idea what this is. } else { codelog(NET__PACKET_ERROR, "sub tuple[0] has invalid type %s", subt->items[0]->TypeString()); _log(NET__PACKET_ERROR, " in:"); payload->Dump( NET__PACKET_ERROR, "" ); PyDecRef(payload); return false; } if(!subt->items[1]->IsTuple()) { codelog(NET__PACKET_ERROR, "subt tuple[1] has non-tuple type %s", robjt->items[0]->TypeString()); _log(NET__PACKET_ERROR, " it is:"); payload->Dump( NET__PACKET_ERROR, "" ); PyDecRef(payload); return false; } args = (PyTuple *) subt->items[1]; subt->items[1] = NULL; notifyType = notify_type; PyDecRef(payload); return true; }
EVENotificationStream::~EVENotificationStream() { PySafeDecRef(args); }
bool PyCallStream::Decode(const std::string &type, PyTuple *&in_payload) { PyTuple *payload = in_payload; //consume in_payload = NULL; PySafeDecRef(arg_tuple); PySafeDecRef(arg_dict); arg_tuple = NULL; arg_dict = NULL; if(type != "macho.CallReq") { codelog(NET__PACKET_ERROR, "failed: packet payload has unknown string type '%s'", type.c_str()); PyDecRef(payload); return false; } if (payload->items.size() != 1) { codelog(NET__PACKET_ERROR, "invalid tuple length %lu", payload->items.size()); PyDecRef(payload); return false; } if (!payload->items[0]->IsTuple()) { codelog(NET__PACKET_ERROR, "non tuple payload[0]"); PyDecRef(payload); return false; } PyTuple *payload2 = (PyTuple *) payload->items[0]; if(payload2->items.size() != 2) { codelog(NET__PACKET_ERROR, "invalid tuple2 length %lu", payload2->items.size()); PyDecRef(payload); return false; } //decode inner payload tuple //ignore tuple 0, it should be an int, dont know what it is if(!payload2->items[1]->IsSubStream()) { codelog(NET__PACKET_ERROR, "non-substream type"); PyDecRef(payload); return false; } PySubStream *ss = (PySubStream *) payload2->items[1]; ss->DecodeData(); if(ss->decoded() == NULL) { codelog(NET__PACKET_ERROR, "Unable to decode call stream"); PyDecRef(payload); return false; } if(!ss->decoded()->IsTuple()) { codelog(NET__PACKET_ERROR, "packet body does not contain a tuple"); PyDecRef(payload); return false; } PyTuple *maint = (PyTuple *) ss->decoded(); if(maint->items.size() != 4) { codelog(NET__PACKET_ERROR, "packet body has %lu elements, expected %d", maint->items.size(), 4); PyDecRef(payload); return false; } //parse first tuple element, unknown if(maint->items[0]->IsInt()) { PyInt *tuple0 = (PyInt *) maint->items[0]; remoteObject = tuple0->value(); remoteObjectStr = ""; } else if(maint->items[0]->IsString()) { PyString *tuple0 = (PyString *) maint->items[0]; remoteObject = 0; remoteObjectStr = tuple0->content(); } else { codelog(NET__PACKET_ERROR, "tuple[0] has invalid type %s", maint->items[0]->TypeString()); codelog(NET__PACKET_ERROR, " in:"); payload->Dump(NET__PACKET_ERROR, " "); PyDecRef(payload); return false; } //parse tuple[1]: method name if(maint->items[1]->IsString()) { PyString *i = (PyString *) maint->items[1]; method = i->content(); } else { codelog(NET__PACKET_ERROR, "tuple[1] has non-string type"); maint->items[1]->Dump(NET__PACKET_ERROR, " --> "); codelog(NET__PACKET_ERROR, " in:"); payload->Dump(NET__PACKET_ERROR, " "); PyDecRef(payload); return false; } //grab argument list. if(!maint->items[2]->IsTuple()) { codelog(NET__PACKET_ERROR, "argument list has non-tuple type"); maint->items[2]->Dump(NET__PACKET_ERROR, " --> "); codelog(NET__PACKET_ERROR, "in:"); payload->Dump(NET__PACKET_ERROR, " "); PyDecRef(payload); return false; } arg_tuple = (PyTuple *) maint->items[2]; maint->items[2] = NULL; //we keep this one //options dict if(maint->items[3]->IsNone()) { arg_dict = NULL; } else if(maint->items[3]->IsDict()) { arg_dict = (PyDict *) maint->items[3]; maint->items[3] = NULL; //we keep this too. } else { codelog(NET__PACKET_ERROR, "tuple[3] has non-dict type"); maint->items[3]->Dump(NET__PACKET_ERROR, " --> "); codelog(NET__PACKET_ERROR, "in:"); payload->Dump(NET__PACKET_ERROR, " "); PyDecRef(payload); return false; } PyDecRef(payload); return true; }
PyCallStream::~PyCallStream() { PySafeDecRef(arg_tuple); PySafeDecRef(arg_dict); }
PyPacket::~PyPacket() { PySafeDecRef(payload); PySafeDecRef(named_payload); }
PyException::~PyException() { PySafeDecRef( ssException ); }
void Character::UpdateSkillQueue() { Client *c = m_factory.entity_list.FindCharacter( itemID() ); SkillRef currentTraining = GetSkillInTraining(); if( currentTraining ) { if( m_skillQueue.empty() || currentTraining->typeID() != m_skillQueue.front().typeID ) { // either queue is empty or skill with different typeID is in training ... // stop training: _log( ITEM__ERROR, "%s (%u): Stopping training of skill %s (%u).", itemName().c_str(), itemID(), currentTraining->itemName().c_str(), currentTraining->itemID() ); /* uint64 timeEndTrain = currentTraining->expiryTime(); if(timeEndTrain != 0) { double nextLevelSP = currentTraining->GetSPForLevel( currentTraining->skillLevel() + 1 ); double SPPerMinute = GetSPPerMin( currentTraining ); double minRemaining = (double)(timeEndTrain - Win32TimeNow()) / (double)Win32Time_Minute; currentTraining->Set_skillPoints( nextLevelSP - (minRemaining * SPPerMinute) ); } currentTraining->Clear_expiryTime(); */ EvilNumber timeEndTrain = currentTraining->GetAttribute(AttrExpiryTime); if (timeEndTrain != 0) { EvilNumber nextLevelSP = currentTraining->GetSPForLevel( currentTraining->GetAttribute(AttrSkillLevel) + 1 ); EvilNumber SPPerMinute = GetSPPerMin( currentTraining ); EvilNumber minRemaining = (timeEndTrain - EvilNumber(Win32TimeNow())) / (double)Win32Time_Minute; //currentTraining->Set_skillPoints( nextLevelSP - (minRemaining * SPPerMinute) ); currentTraining->SetAttribute(AttrSkillPoints, nextLevelSP - (minRemaining * SPPerMinute)); } currentTraining->SetAttribute(AttrExpiryTime, 0); currentTraining->MoveInto( *this, flagSkill, true ); if( c != NULL ) { OnSkillTrainingStopped osst; osst.itemID = currentTraining->itemID(); osst.endOfTraining = 0; PyTuple* tmp = osst.Encode(); c->QueueDestinyEvent( &tmp ); PySafeDecRef( tmp ); c->UpdateSkillTraining(); } // nothing currently in training currentTraining = SkillRef(); } } EvilNumber nextStartTime = EvilTimeNow(); while( !m_skillQueue.empty() ) { if( !currentTraining ) { // something should be trained, get desired skill uint32 skillTypeID = m_skillQueue.front().typeID; currentTraining = GetSkill( skillTypeID ); if( !currentTraining ) { _log( ITEM__ERROR, "%s (%u): Skill %u to train was not found.", itemName().c_str(), itemID(), skillTypeID ); break; } _log( ITEM__TRACE, "%s (%u): Starting training of skill %s (%u).", m_itemName.c_str(), m_itemID, currentTraining->itemName().c_str(), currentTraining->itemID() ); EvilNumber SPPerMinute = GetSPPerMin( currentTraining ); // double SPToNextLevel = currentTraining->GetSPForLevel( currentTraining->skillLevel() + 1 ) - currentTraining->skillPoints(); EvilNumber SPToNextLevel = currentTraining->GetSPForLevel( currentTraining->GetAttribute(AttrSkillLevel) + 1) - currentTraining->GetAttribute(AttrSkillPoints); //uint64 timeTraining = nextStartTime + Win32Time_Minute * SPToNextLevel / SPPerMinute; EvilNumber timeTraining = nextStartTime + EvilTime_Minute * SPToNextLevel / SPPerMinute; currentTraining->MoveInto( *this, flagSkillInTraining ); //currentTraining->Set_expiryTime( timeTraining ); currentTraining->SetAttribute(AttrExpiryTime, timeTraining); if( c != NULL ) { OnSkillStartTraining osst; osst.itemID = currentTraining->itemID(); osst.endOfTraining = timeTraining.get_int(); PyTuple* tmp = osst.Encode(); c->QueueDestinyEvent( &tmp ); PySafeDecRef( tmp ); c->UpdateSkillTraining(); } } //if( currentTraining->expiryTime() <= Win32TimeNow() ) if( currentTraining->GetAttribute(AttrExpiryTime) <= EvilTimeNow() ) { // training has been finished: _log( ITEM__ERROR, "%s (%u): Finishing training of skill %s (%u).", itemName().c_str(), itemID(), currentTraining->itemName().c_str(), currentTraining->itemID() ); //currentTraining->Set_skillLevel( currentTraining->skillLevel() + 1 ); //currentTraining->Set_skillPoints( currentTraining->GetSPForLevel( currentTraining->skillLevel() ) ); //nextStartTime = currentTraining->expiryTime(); //currentTraining->Clear_expiryTime(); currentTraining->SetAttribute(AttrSkillLevel, currentTraining->GetAttribute(AttrSkillLevel) + 1 ); currentTraining->SetAttribute(AttrSkillPoints, currentTraining->GetSPForLevel( currentTraining->GetAttribute(AttrSkillLevel) ) ); nextStartTime = currentTraining->GetAttribute(AttrExpiryTime); currentTraining->SetAttribute(AttrExpiryTime, 0); currentTraining->MoveInto( *this, flagSkill, true ); if( c != NULL ) { OnSkillTrained ost; ost.itemID = currentTraining->itemID(); PyTuple* tmp = ost.Encode(); c->QueueDestinyEvent( &tmp ); PySafeDecRef( tmp ); c->UpdateSkillTraining(); } // erase first element in skill queue m_skillQueue.erase( m_skillQueue.begin() ); // nothing currently in training currentTraining = SkillRef(); } // else the skill is in training ... else break; } // Re-Calculate total SP trained and store in internal variable: _CalculateTotalSPTrained(); // Save character and skill data: SaveCharacter(); SaveSkillQueue(); }
PyResult::~PyResult() { PySafeDecRef( ssResult ); }
void Character::UpdateSkillQueue() { Client *c = m_factory.entity_list.FindCharacter( itemID() ); SkillRef currentTraining = GetSkillInTraining(); if( currentTraining ) { if( m_skillQueue.empty() || currentTraining->typeID() != m_skillQueue.front().typeID ) { // either queue is empty or skill with different typeID is in training ... // stop training: _log( ITEM__ERROR, "%s (%u): Stopping training of skill %s (%u).", itemName().c_str(), itemID(), currentTraining->itemName().c_str(), currentTraining->itemID() ); /* uint64 timeEndTrain = currentTraining->expiryTime(); if(timeEndTrain != 0) { double nextLevelSP = currentTraining->GetSPForLevel( currentTraining->skillLevel() + 1 ); double SPPerMinute = GetSPPerMin( currentTraining ); double minRemaining = (double)(timeEndTrain - Win32TimeNow()) / (double)Win32Time_Minute; currentTraining->Set_skillPoints( nextLevelSP - (minRemaining * SPPerMinute) ); } currentTraining->Clear_expiryTime(); */ EvilNumber timeEndTrain = currentTraining->GetAttribute(AttrExpiryTime); if (timeEndTrain != 0) { EvilNumber nextLevelSP = currentTraining->GetSPForLevel( currentTraining->GetAttribute(AttrSkillLevel) + 1 ); EvilNumber SPPerMinute = GetSPPerMin( currentTraining ); EvilNumber minRemaining = (timeEndTrain - EvilNumber(Win32TimeNow())) / (double)Win32Time_Minute; //currentTraining->Set_skillPoints( nextLevelSP - (minRemaining * SPPerMinute) ); EvilNumber skillPointsTrained = nextLevelSP - (minRemaining * SPPerMinute); currentTraining->SetAttribute(AttrSkillPoints, skillPointsTrained); sLog.Debug( "", "Skill %s (%u) trained %u skill points before termination from training queue", currentTraining->itemName().c_str(), currentTraining->itemID(), skillPointsTrained.get_float() ); } currentTraining->SetAttribute(AttrExpiryTime, 0); currentTraining->MoveInto( *this, flagSkill, true ); if( c != NULL ) { OnSkillTrainingStopped osst; osst.itemID = currentTraining->itemID(); osst.endOfTraining = 0; PyTuple* tmp = osst.Encode(); c->QueueDestinyEvent( &tmp ); PySafeDecRef( tmp ); c->UpdateSkillTraining(); } // nothing currently in training currentTraining = SkillRef(); } } EvilNumber nextStartTime = EvilTimeNow(); while( !m_skillQueue.empty() ) { if( !currentTraining ) { // something should be trained, get desired skill uint32 skillTypeID = m_skillQueue.front().typeID; currentTraining = GetSkill( skillTypeID ); if( !currentTraining ) { _log( ITEM__ERROR, "%s (%u): Skill %u to train was not found.", itemName().c_str(), itemID(), skillTypeID ); break; } sLog.Debug( "Character::UpdateSkillQueue()", "%s (%u): Starting training of skill %s (%u)", m_itemName.c_str(), m_itemID, currentTraining->itemName().c_str(), currentTraining->itemID() ); EvilNumber SPPerMinute = GetSPPerMin( currentTraining ); EvilNumber NextLevel = currentTraining->GetAttribute(AttrSkillLevel) + 1; EvilNumber SPToNextLevel = currentTraining->GetSPForLevel( NextLevel ) - currentTraining->GetAttribute(AttrSkillPoints); sLog.Debug( " ", "Training skill at %f SP/min", SPPerMinute.get_float() ); sLog.Debug( " ", "%f SP to next Level of %d", SPToNextLevel.get_float(), NextLevel.get_int() ); SPPerMinute.to_float(); SPToNextLevel.to_float(); nextStartTime.to_float(); EvilNumber timeTraining = nextStartTime + EvilTime_Minute * SPToNextLevel / SPPerMinute; currentTraining->MoveInto( *this, flagSkillInTraining ); double dbl_timeTraining = timeTraining.get_float() + (double)(Win32Time_Second * 10); currentTraining->SetAttribute(AttrExpiryTime, dbl_timeTraining); // Set server-side // skill expiry + 10 sec sLog.Debug( " ", "Calculated time to complete training = %s", Win32TimeToString((uint64)dbl_timeTraining).c_str() ); if( c != NULL ) { OnSkillStartTraining osst; osst.itemID = currentTraining->itemID(); osst.endOfTraining = timeTraining.get_float(); PyTuple* tmp = osst.Encode(); c->QueueDestinyEvent( &tmp ); PySafeDecRef( tmp ); c->UpdateSkillTraining(); } } if( currentTraining->GetAttribute(AttrExpiryTime) <= EvilTimeNow() ) { // training has been finished: sLog.Debug( "Character::UpdateSkillQueue()", "%s (%u): Finishing training of skill %s (%u).", itemName().c_str(), itemID(), currentTraining->itemName().c_str(), currentTraining->itemID() ); currentTraining->SetAttribute(AttrSkillLevel, currentTraining->GetAttribute(AttrSkillLevel) + 1 ); currentTraining->SetAttribute(AttrSkillPoints, currentTraining->GetSPForLevel( currentTraining->GetAttribute(AttrSkillLevel) ), true); nextStartTime = currentTraining->GetAttribute(AttrExpiryTime); currentTraining->SetAttribute(AttrExpiryTime, 0); currentTraining->MoveInto( *this, flagSkill, true ); if( c != NULL ) { OnSkillTrained ost; ost.itemID = currentTraining->itemID(); PyTuple* tmp = ost.Encode(); c->QueueDestinyEvent( &tmp ); PySafeDecRef( tmp ); c->UpdateSkillTraining(); } // erase first element in skill queue m_skillQueue.erase( m_skillQueue.begin() ); // nothing currently in training currentTraining = SkillRef(); } // else the skill is in training ... else break; } // Re-Calculate total SP trained and store in internal variable: _CalculateTotalSPTrained(); // Save character and skill data: SaveCharacter(); SaveSkillQueue(); }
// This is a NPC implementation of damage system (incomplete) bool NPC::ApplyDamage(Damage &d) { _log(ITEM__TRACE, "%u: Applying %.1f total damage from %u", GetID(), d.GetTotal(), d.source->GetID()); double total_damage = 0; bool killed = false; int random_damage = 0; double random_damage_mult = 1.0; //apply resistances... //damageResistance? //Shield: double available_shield = m_shieldCharge; Damage shield_damage = d.MultiplyDup( m_self->GetAttribute(AttrShieldKineticDamageResonance).get_float(), m_self->GetAttribute(AttrShieldThermalDamageResonance).get_float(), m_self->GetAttribute(AttrShieldEmDamageResonance).get_float(), m_self->GetAttribute(AttrShieldExplosiveDamageResonance).get_float() ); //other: //emDamageResistanceBonus //explosiveDamageResistanceBonus //kineticDamageResistanceBonus //thermalDamageResistanceBonus // //TODO: deal with seepage from shield into armor. //shieldUniformity //uniformity (chance of seeping through to armor) /* * Here we calculates the uniformity thing. * I think this must be calculated based on * the type of damage -> resistance basis. * double shield_uniformity = available_shield / m_self->shieldCapacity(); if( shield_uniformity < ( 1.0 - m_self->shieldUniformity() ) ) { /* * As far i can see mostly npc/entities have a * chance of transpassing when the shield is below 25% / } */ // Make a random value to use in msg's and attack multiplier random_damage = static_cast<int32>(MakeRandomInt(0, 5)); random_damage_mult = (double)(random_damage / 10.0); // Not sure about this, but with this we get some random hits... :) //total_shield_damage += total_shield_damage * random_damage_mult; shield_damage.SumWithMultFactor( random_damage_mult ); double total_shield_damage = shield_damage.GetTotal(); if(total_shield_damage <= available_shield) { //we can take all this damage with our shield... double new_charge = m_shieldCharge - total_shield_damage; m_shieldCharge = new_charge; total_damage += total_shield_damage; _log(ITEM__TRACE, "%s(%u): Applying entire %.1f damage to shields. New charge: %.1f", GetName(), GetID(), total_shield_damage, new_charge); } else { //first determine how much we can actually apply to //the shield, the rest goes further down. double consumed_shield_ratio = available_shield / shield_damage.GetTotal(); d *= 1.0 - consumed_shield_ratio; if(available_shield > 0) { total_damage += available_shield; _log(ITEM__TRACE, "%s(%us): Shield depleated with %.1f damage. %.1f damage remains.", GetName(), GetID(), available_shield, d.GetTotal()); //set shield to 0, it is fully depleated. m_shieldCharge = 0; } //Armor: double available_armor = m_self->GetAttribute(AttrArmorHP).get_float() - m_armorDamage; Damage armor_damage = d.MultiplyDup( m_self->GetAttribute(AttrArmorKineticDamageResonance).get_float(), m_self->GetAttribute(AttrArmorThermalDamageResonance).get_float(), m_self->GetAttribute(AttrArmorEmDamageResonance).get_float(), m_self->GetAttribute(AttrArmorExplosiveDamageResonance).get_float() ); //other: //activeEmResistanceBonus //activeExplosiveResistanceBonus //activeThermicResistanceBonus //activeKineticResistanceBonus //passiveEmDamageResistanceBonus //passiveExplosiveDamageResistanceBonus //passiveKineticDamageResistanceBonus //passiveThermicDamageResistanceBonus //TODO: figure out how much passes through to structure/modules. //armorUniformity // Not sure about this, but with this we get some random hits... :) //total_armor_damage += total_armor_damage * random_damage_mult; armor_damage.SumWithMultFactor( random_damage_mult ); double total_armor_damage = armor_damage.GetTotal(); if(total_armor_damage <= available_armor) { //we can take all this damage with our armor... double new_damage = m_armorDamage + total_armor_damage; m_armorDamage = new_damage; total_damage += total_armor_damage; _log(ITEM__TRACE, "%s(%u): Applying entire %.1f damage to armor. New armor damage: %.1f", GetName(), GetID(), total_armor_damage, new_damage); } else { //first determine how much we can actually apply to //the armor, the rest goes further down. double consumed_armor_ratio = available_armor / armor_damage.GetTotal(); d *= 1.0 - consumed_armor_ratio; if(available_armor > 0) { total_damage += available_armor; _log(ITEM__TRACE, "%s(%u): Armor depleated with %.1f damage. %.1f damage remains.", GetName(), GetID(), available_armor, d.GetTotal()); //all armor has been penetrated. m_armorDamage = m_self->GetAttribute(AttrArmorHP).get_float(); } //Hull/Structure: //The base hp and damage attributes represent structure. double available_hull = m_self->GetAttribute(AttrHp).get_float() - m_hullDamage; Damage hull_damage = d.MultiplyDup( m_self->GetAttribute(AttrHullKineticDamageResonance).get_float(), m_self->GetAttribute(AttrHullThermalDamageResonance).get_float(), m_self->GetAttribute(AttrHullEmDamageResonance).get_float(), m_self->GetAttribute(AttrHullExplosiveDamageResonance).get_float() ); //other: //passiveEmDamageResonanceMultiplier //passiveThermalDamageResonanceMultiplier //passiveKineticDamageResonanceMultiplier //passiveExplosiveDamageResonanceMultiplier //activeEmDamageResonance //activeThermalDamageResonance //activeKineticDamageResonance //activeExplosiveDamageResonance //structureUniformity // Not sure about this, but with this we get some random hits... :) //total_hull_damage += total_hull_damage * random_damage_mult; hull_damage.SumWithMultFactor( random_damage_mult ); double total_hull_damage = hull_damage.GetTotal(); total_damage += total_hull_damage; if(total_hull_damage < available_hull) { //we can take all this damage with our hull... double new_damage = m_hullDamage + total_hull_damage; m_hullDamage = new_damage; _log(ITEM__TRACE, "%s(%u): Applying entire %.1f damage to structure. New structure damage: %.1f", GetName(), GetID(), total_hull_damage, new_damage); } else { //dead.... _log(ITEM__TRACE, "%s(%u): %.1f damage has depleated our structure. Time to explode.", GetName(), GetID(), total_hull_damage); killed = true; //m_hullDamage = m_self->hp(); m_hullDamage = m_self->GetAttribute(AttrHp).get_float(); } //TODO: deal with damaging modules. no idea the mechanics on this. } } //if( total_damage <= 0.0 ) // return(killed); PyTuple *up; //Notifications to ourself: Notify_OnEffectHit noeh; noeh.itemID = d.source->GetID(); noeh.effectID = d.effect; noeh.targetID = GetID(); noeh.damage = total_damage; up = noeh.Encode(); QueueDestinyEvent(&up); PySafeDecRef( up ); //NOTE: could send out the RD version of this message instead of the R version, which //includes "weapon" and "owner" instead of "source". Notify_OnDamageMessage_Self ondam; //ondam.messageID = "AttackHit2R"; //TODO: randomize/select this somehow. ondam.messageID = DamageMessageIDs_Self[random_damage]; ondam.damage = total_damage; ondam.source = d.source->GetID(); ondam.splash = ""; up = ondam.Encode(); QueueDestinyEvent(&up); PySafeDecRef( up ); //Notifications to others: //I am not sure what the correct scope of this broadcast //should be. For now, it goes to anybody targeting us. if(targets.IsTargetedBySomething()) { up = noeh.Encode(); targets.QueueTBDestinyEvent(&up); PySafeDecRef( up ); Notify_OnDamageMessage_Other ondamo; //ondamo.messageID = "AttackHit3"; //TODO: select this based on the severity of the hit... ondamo.messageID = DamageMessageIDs_Other[random_damage]; ondamo.format_type = fmtMapping_itemTypeName; ondamo.weaponType = d.weapon->typeID(); ondamo.damage = total_damage; ondamo.target = GetID(); ondamo.splash = ""; up = ondamo.Encode(); targets.QueueTBDestinyEvent(&up); PySafeDecRef( up ); } if(killed == true) { Killed(d); } else { _SendDamageStateChanged(); } return(killed); }