GameItem* LumosChitBag::AddItem(const char* name, Chit* chit, Engine* engine, int team, int level, const char* altRes, const char* altName) { ItemDefDB* itemDefDB = ItemDefDB::Instance(); ItemDefDB::GameItemArr itemDefArr; itemDefDB->Get(name, &itemDefArr); GLASSERT(itemDefArr.Size() > 0); GameItem* item = itemDefArr[0]->Clone(); if (altName) { item->SetName(altName); } if (altRes) { item->SetResource(altRes); } item->Roll(team, item->Traits().Get()); item->GetTraitsMutable()->SetExpFromLevel( level ); item->FullHeal(); if ( !chit->GetItemComponent() ) { ItemComponent* ic = new ItemComponent( item ); chit->Add( ic ); for( int i=1; i<itemDefArr.Size(); ++i ) { GameItem* gi = itemDefArr[i]->Clone(); ic->AddToInventory(gi); } } else { GLASSERT( itemDefArr.Size() == 1 ); chit->GetItemComponent()->AddToInventory(item); } return item; }
void PlayerMoveComponent::update(double deltaTime) { //Prüft die Tastatureingabe und berechnet mit der Beschleunigung die Geschwindigkeit determineDirection(); velocity += deltaTime * accel; if (velocity.getLength() > maxVelocity) { velocity.normalize(); velocity *= maxVelocity; } CVector position = parent->getPosition(); double rotation = parent->getRotation(); position += PIXEL_PER_METER *deltaTime * velocity; angularVelo += deltaTime * angularAccel; if (abs(angularVelo) > maxAngularVelocity) { angularVelo = (angularVelo > 0.0)? maxAngularVelocity : - maxAngularVelocity; } rotation += deltaTime * angularVelo; if (rotation > 360.0) rotation -= 360.0; if (rotation < -360.0) rotation += 360.0; //Prüfen ob der Spieler aus dem Bild laufen würde if (position[0] + playerSize > 1024) { position[0] = 1024 - playerSize; velocity[0] *= -0.2; } if (position[0] < 0 + playerSize) { position[0] = 0 + playerSize; velocity[0] *= -0.2; } if (position[1] + playerSize + 20 > 800) { position[1] = 800 - playerSize - 20; velocity[1] *= -0.2; } if (position[1] < 0 + playerSize + 10) { position[1] = 0 + playerSize + 10; velocity[1] *= -0.2; } parent->setPosition(position); //Kollisionsabfrage quadColission(); //Prüfen ob der Spieler einen Gegenstand aufnehmen würde Character *item = CharacterManager::instance()->getCharacter("Item"); ItemComponent *itemComp = getComponent<ItemComponent>(item); if((item->getPosition()-getPosition()).getLength() < 50.0f){ itemComp->pickUp(); score++; } }
void GameHandler::handlePickup(GameClient &client, MessageIn &message) { const int x = message.readInt16(); const int y = message.readInt16(); const Point ppos = client.character->getComponent<ActorComponent>()->getPosition(); // TODO: use a less arbitrary value. if (std::abs(x - ppos.x) + std::abs(y - ppos.y) < 48) { MapComposite *map = client.character->getMap(); Point ipos(x, y); for (FixedActorIterator i(map->getAroundPointIterator(ipos, 0)); i; ++i) { Entity *o = *i; Point opos = o->getComponent<ActorComponent>()->getPosition(); if (o->getType() == OBJECT_ITEM && opos.x == x && opos.y == y) { ItemComponent *item = o->getComponent<ItemComponent>(); ItemClass *ic = item->getItemClass(); int amount = item->getAmount(); if (!Inventory(client.character).insert(ic->getDatabaseID(), amount)) { GameState::remove(o); // We only do this when items are to be kept in memory // between two server restart. if (!Configuration::getValue("game_floorItemDecayTime", 0)) { // Remove the floor item from map accountHandler->removeFloorItems(map->getID(), ic->getDatabaseID(), amount, x, y); } // log transaction std::stringstream str; str << "User picked up item " << ic->getDatabaseID() << " at " << opos.x << "x" << opos.y; auto *characterComponent = client.character ->getComponent<CharacterComponent>(); accountHandler->sendTransaction( characterComponent->getDatabaseID(), TRANS_ITEM_PICKUP, str.str() ); } break; } } } }
/** * Informs a player of what happened around the character. */ static void informPlayer(MapComposite *map, Character *p) { MessageOut moveMsg(GPMSG_BEINGS_MOVE); MessageOut damageMsg(GPMSG_BEINGS_DAMAGE); const Point &pold = p->getOldPosition(), ppos = p->getPosition(); int pid = p->getPublicID(), pflags = p->getUpdateFlags(); int visualRange = Configuration::getValue("game_visualRange", 448); // Inform client about activities of other beings near its character for (BeingIterator it(map->getAroundBeingIterator(p, visualRange)); it; ++it) { Being *o = *it; const Point &oold = o->getOldPosition(), opos = o->getPosition(); int otype = o->getType(); int oid = o->getPublicID(), oflags = o->getUpdateFlags(); int flags = 0; // Check if the character p and the moving object o are around. bool wereInRange = pold.inRangeOf(oold, visualRange) && !((pflags | oflags) & UPDATEFLAG_NEW_ON_MAP); bool willBeInRange = ppos.inRangeOf(opos, visualRange); if (!wereInRange && !willBeInRange) { // Nothing to report: o and p are far away from each other. continue; } if (wereInRange && willBeInRange) { // Send attack messages. if ((oflags & UPDATEFLAG_ATTACK) && oid != pid) { MessageOut AttackMsg(GPMSG_BEING_ATTACK); AttackMsg.writeInt16(oid); AttackMsg.writeInt8(o->getDirection()); AttackMsg.writeInt8(static_cast< Being * >(o)->getAttackId()); gameHandler->sendTo(p, AttackMsg); } // Send action change messages. if ((oflags & UPDATEFLAG_ACTIONCHANGE)) { MessageOut ActionMsg(GPMSG_BEING_ACTION_CHANGE); ActionMsg.writeInt16(oid); ActionMsg.writeInt8(static_cast< Being * >(o)->getAction()); gameHandler->sendTo(p, ActionMsg); } // Send looks change messages. if (oflags & UPDATEFLAG_LOOKSCHANGE) { MessageOut LooksMsg(GPMSG_BEING_LOOKS_CHANGE); LooksMsg.writeInt16(oid); Character * c = static_cast<Character * >(o); serializeLooks(c, LooksMsg); LooksMsg.writeInt16(c->getHairStyle()); LooksMsg.writeInt16(c->getHairColor()); LooksMsg.writeInt16(c->getGender()); gameHandler->sendTo(p, LooksMsg); } // Send emote messages. if (oflags & UPDATEFLAG_EMOTE) { int emoteId = o->getLastEmote(); if (emoteId > -1) { MessageOut EmoteMsg(GPMSG_BEING_EMOTE); EmoteMsg.writeInt16(oid); EmoteMsg.writeInt16(emoteId); gameHandler->sendTo(p, EmoteMsg); } } // Send direction change messages. if (oflags & UPDATEFLAG_DIRCHANGE) { MessageOut DirMsg(GPMSG_BEING_DIR_CHANGE); DirMsg.writeInt16(oid); DirMsg.writeInt8(o->getDirection()); gameHandler->sendTo(p, DirMsg); } // Send damage messages. if (o->canFight()) { Being *victim = static_cast< Being * >(o); const Hits &hits = victim->getHitsTaken(); for (Hits::const_iterator j = hits.begin(), j_end = hits.end(); j != j_end; ++j) { damageMsg.writeInt16(oid); damageMsg.writeInt16(*j); } } if (oold == opos) { // o does not move, nothing more to report. continue; } } if (!willBeInRange) { // o is no longer visible from p. Send leave message. MessageOut leaveMsg(GPMSG_BEING_LEAVE); leaveMsg.writeInt16(oid); gameHandler->sendTo(p, leaveMsg); continue; } if (!wereInRange) { // o is now visible by p. Send enter message. MessageOut enterMsg(GPMSG_BEING_ENTER); enterMsg.writeInt8(otype); enterMsg.writeInt16(oid); enterMsg.writeInt8(static_cast< Being *>(o)->getAction()); enterMsg.writeInt16(opos.x); enterMsg.writeInt16(opos.y); enterMsg.writeInt8(o->getDirection()); enterMsg.writeInt8(o->getGender()); switch (otype) { case OBJECT_CHARACTER: { Character *q = static_cast< Character * >(o); enterMsg.writeString(q->getName()); enterMsg.writeInt8(q->getHairStyle()); enterMsg.writeInt8(q->getHairColor()); serializeLooks(q, enterMsg); } break; case OBJECT_MONSTER: { Monster *q = static_cast< Monster * >(o); enterMsg.writeInt16(q->getSpecy()->getId()); enterMsg.writeString(q->getName()); } break; case OBJECT_NPC: { NpcComponent *npcComponent = o->getComponent<NpcComponent>(); enterMsg.writeInt16(npcComponent->getNpcId()); enterMsg.writeString(o->getName()); } break; default: assert(false); // TODO break; } gameHandler->sendTo(p, enterMsg); } if (opos != oold) { // Add position check coords every 5 seconds. if (currentTick % 50 == 0) flags |= MOVING_POSITION; flags |= MOVING_DESTINATION; } // Send move messages. moveMsg.writeInt16(oid); moveMsg.writeInt8(flags); if (flags & MOVING_POSITION) { moveMsg.writeInt16(oold.x); moveMsg.writeInt16(oold.y); } if (flags & MOVING_DESTINATION) { moveMsg.writeInt16(opos.x); moveMsg.writeInt16(opos.y); // We multiply the sent speed (in tiles per second) by ten // to get it within a byte with decimal precision. // For instance, a value of 4.5 will be sent as 45. moveMsg.writeInt8((unsigned short) (o->getModifiedAttribute(ATTR_MOVE_SPEED_TPS) * 10)); } } // Do not send a packet if nothing happened in p's range. if (moveMsg.getLength() > 2) gameHandler->sendTo(p, moveMsg); if (damageMsg.getLength() > 2) gameHandler->sendTo(p, damageMsg); // Inform client about status change. p->sendStatus(); // Inform client about health change of party members for (CharacterIterator i(map->getWholeMapIterator()); i; ++i) { Character *c = *i; // Make sure its not the same character if (c == p) continue; // make sure they are in the same party if (c->getParty() == p->getParty()) { int cflags = c->getUpdateFlags(); if (cflags & UPDATEFLAG_HEALTHCHANGE) { MessageOut healthMsg(GPMSG_BEING_HEALTH_CHANGE); healthMsg.writeInt16(c->getPublicID()); healthMsg.writeInt16(c->getModifiedAttribute(ATTR_HP)); healthMsg.writeInt16(c->getModifiedAttribute(ATTR_MAX_HP)); gameHandler->sendTo(p, healthMsg); } } } // Inform client about items on the ground around its character MessageOut itemMsg(GPMSG_ITEMS); for (FixedActorIterator it(map->getAroundBeingIterator(p, visualRange)); it; ++it) { Actor *o = *it; assert(o->getType() == OBJECT_ITEM || o->getType() == OBJECT_EFFECT); Point opos = o->getPosition(); int oflags = o->getUpdateFlags(); bool willBeInRange = ppos.inRangeOf(opos, visualRange); bool wereInRange = pold.inRangeOf(opos, visualRange) && !((pflags | oflags) & UPDATEFLAG_NEW_ON_MAP); if (willBeInRange ^ wereInRange) { switch (o->getType()) { case OBJECT_ITEM: { ItemComponent *item = o->getComponent<ItemComponent>(); ItemClass *itemClass = item->getItemClass(); if (oflags & UPDATEFLAG_NEW_ON_MAP) { /* Send a specific message to the client when an item appears out of nowhere, so that a sound/animation can be performed. */ MessageOut appearMsg(GPMSG_ITEM_APPEAR); appearMsg.writeInt16(itemClass->getDatabaseID()); appearMsg.writeInt16(opos.x); appearMsg.writeInt16(opos.y); gameHandler->sendTo(p, appearMsg); } else { itemMsg.writeInt16(willBeInRange ? itemClass->getDatabaseID() : 0); itemMsg.writeInt16(opos.x); itemMsg.writeInt16(opos.y); } } break; case OBJECT_EFFECT: { EffectComponent *e = o->getComponent<EffectComponent>(); e->setShown(); // Don't show old effects if (!(oflags & UPDATEFLAG_NEW_ON_MAP)) break; if (Being *b = e->getBeing()) { MessageOut effectMsg(GPMSG_CREATE_EFFECT_BEING); effectMsg.writeInt16(e->getEffectId()); effectMsg.writeInt16(b->getPublicID()); gameHandler->sendTo(p, effectMsg); } else { MessageOut effectMsg(GPMSG_CREATE_EFFECT_POS); effectMsg.writeInt16(e->getEffectId()); effectMsg.writeInt16(opos.x); effectMsg.writeInt16(opos.y); gameHandler->sendTo(p, effectMsg); } } break; default: break; } // Switch } } // Do not send a packet if nothing happened in p's range. if (itemMsg.getLength() > 2) gameHandler->sendTo(p, itemMsg); }
void CoreScript::DoStrategicTick() { // Look around for someone to attack. They should be: // - someone we have a negative attitude about (accounts for lots of things) // - weaker overall // // We should: // - have a reasonably armed squad bool squadReady[MAX_SQUADS] = { false }; CChitArray squaddies; // Check for ready squads. for (int i = 0; i < MAX_SQUADS; ++i) { this->Squaddies(i, &squaddies); if (squaddies.Size() < SQUAD_SIZE) continue; if (!SquadAtRest(i)) continue; // Do we have enough guns? Seems to be // the best / easiest metric. int nGuns = 0; for (int k = 0; k < squaddies.Size(); ++k) { Chit* chit = squaddies[k]; ItemComponent* ic = chit->GetItemComponent(); if ( chit->GetItem() && chit->GetItem()->HPFraction() > 0.75f && ic && ic->QuerySelectRanged()) { nGuns++; } } squadReady[i] = nGuns >= SQUAD_SIZE - 1; } int nReady = 0; for (int i = 0; i < MAX_SQUADS; ++i) { if (squadReady[i]) ++nReady; } Sim* sim = Context()->chitBag->GetSim(); GLASSERT(sim); if (!sim) return; Vector2I sector = ToSector(ParentChit()->Position()); CCoreArray stateArr; sim->CalcStrategicRelationships(sector, 3, &stateArr); // The strategic relationships need to be calculated, but after that, // there's no point in computing further if we don't have a squad to // send into action. if (nReady == 0) return; int myPower = this->CorePower(); CoreScript* target = 0; for (int i = 0; i < stateArr.Size(); ++i) { CoreScript* cs = stateArr[i]; if (cs->NumTemples() == 0) // Ignore starting out domains so it isn't a complete wasteland out there. continue; if ( Team::Instance()->GetRelationship(cs->ParentChit(), this->ParentChit()) == ERelate::ENEMY // Are we enemies at the diplomatic level && Team::Instance()->Attitude(this, cs) < 0) // Does 'this' have a negative attitude to the other? { int power = cs->CorePower(); if (power < myPower * 0.75f) { // Assuming this is actually so rare that it doesn't matter to select the best. target = cs; break; } } } if (!target) return; // Attack!!! bool first = true; Vector2F targetCorePos2 = ToWorld2F(target->ParentChit()->Position()); Vector2I targetCorePos = ToWorld2I(target->ParentChit()->Position());; Vector2I targetSector = ToSector(targetCorePos); for (int i = 0; i < MAX_SQUADS; ++i) { if (!squadReady[i]) continue; Vector2I pos = { 0, 0 }; pos = targetCorePos; if (first) { first = false; } else { BuildingWithPorchFilter filter; Chit* building = Context()->chitBag->FindBuilding(IString(), targetSector, &targetCorePos2, LumosChitBag::EFindMode::RANDOM_NEAR, 0, &filter); if (building) { pos = ToWorld2I(building->Position()); } } GLASSERT(!pos.IsZero()); this->SetWaypoints(i, pos); } }