Beispiel #1
0
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 );
}
Beispiel #5
0
PyException& PyException::operator=( const PyException& oth )
{
    PySafeDecRef( ssException );
    ssException = oth.ssException;

    if( NULL != ssException )
        PyIncRef( ssException );

    return *this;
}
Beispiel #6
0
PyResult& PyResult::operator=( const PyResult& oth )
{
    PySafeDecRef( ssResult );
    ssResult = oth.ssResult;

    if( NULL != ssResult )
        PyIncRef( ssResult );

    return *this;
}
Beispiel #7
0
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;
}
Beispiel #10
0
//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 );
}
Beispiel #11
0
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 );
}
Beispiel #12
0
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 );
}
Beispiel #14
0
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;
}
Beispiel #15
0
PyCachedCall::~PyCachedCall()
{
    PySafeDecRef( result );
}
Beispiel #16
0
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;
}
Beispiel #17
0
PyCachedObject::~PyCachedObject()
{
    PySafeDecRef( cache );
    PySafeDecRef( objectID );
}
Beispiel #18
0
PyCachedObjectDecoder::~PyCachedObjectDecoder()
{
    PySafeDecRef( cache );
    PySafeDecRef( objectID );
}
Beispiel #19
0
bool EVENotificationStream::Decode(const std::string &pkt_type, const std::string &notify_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;
}
Beispiel #20
0
EVENotificationStream::~EVENotificationStream() {
    PySafeDecRef(args);
}
Beispiel #21
0
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;
}
Beispiel #22
0
PyCallStream::~PyCallStream() {
    PySafeDecRef(arg_tuple);
    PySafeDecRef(arg_dict);
}
Beispiel #23
0
PyPacket::~PyPacket()
{
    PySafeDecRef(payload);
    PySafeDecRef(named_payload);
}
Beispiel #24
0
PyException::~PyException() { PySafeDecRef( ssException ); }
Beispiel #25
0
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();
}
Beispiel #26
0
PyResult::~PyResult() { PySafeDecRef( ssResult ); }
Beispiel #27
0
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();
}
Beispiel #28
0
// 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);

}