public void ThrowItem(int character, int item, Position pos) { //UISystem.Message(DescriptionSystem.GetNameWithID(character) + " throws " + DescriptionSystem.GetNameWithID(item) + " at " + pos); UISystem.Message(DescriptionSystem.GetName(character) + " throws " + DescriptionSystem.GetName(item)); if (Util.CurrentFloor.IsTileBlocked(pos)) { UISystem.Message("You can't throw that there!"); return; } int targetCharacter = Util.CurrentFloor.GetCharacter(pos); if (targetCharacter == 0) { Util.CurrentFloor.PlaceItem(pos, item); } else { UISystem.Message("It hits " + DescriptionSystem.GetName(targetCharacter) + "!"); // TODO: actually calulate the modifier for effects of thrown items float modifier = 0.5f; ApplySubstance(targetCharacter, item, modifier); IdentifyItem(item); DecreaseItemCount(character, item); TryDeleteItem(item); } Util.TurnOver(character); }
void ResolveProperty(Property prop, int value, int target) { switch (prop) { // --- Resource --- // case Property.Health: if (value < 0) { HealthLostEvent?.Invoke(target, -value); } else { HealthGainedEvent?.Invoke(target, value); } break; // --- Stat --- // case Property.Str: case Property.Dex: case Property.Int: case Property.Fire: case Property.Nature: case Property.Water: case Property.Wind: Stat stat = prop.ToStat(); StatChangedEvent?.Invoke(target, stat, value, Math.Abs(value * 2)); break; default: UISystem.Message(String.Format("Item effect not implemented: {0} ({1})", prop.ToString(), value)); break; } }
public void PickUpItem(int character) { Position position = EntityManager.GetComponent <TransformComponent>(character).Position; int pickupItemID = Util.CurrentFloor.GetFirstItem(position); if (pickupItemID == 0) { UISystem.Message("Nothing here to be picked up!"); return; } bool success = AddItem(character, pickupItemID); if (!success) { return; } // post message to player UISystem.Message(DescriptionSystem.GetNameWithID(character) + " picked up " + DescriptionSystem.GetNameWithID(pickupItemID)); Util.CurrentFloor.RemoveItem(position, pickupItemID); Util.TurnOver(character); }
public void UseItem(int character, int item, ItemUsage usage) { var usableItem = EntityManager.GetComponent <UsableItemComponent>(item); if (usableItem == null) { UISystem.Message("You can't use that!"); return; } if (!usableItem.Usages.Contains(usage)) { UISystem.Message("You can't use that like that!"); return; } UISystem.Message(DescriptionSystem.GetNameWithID(character) + " uses " + DescriptionSystem.GetNameWithID(item) + " -> " + usage); switch (usage) { case ItemUsage.Consume: ConsumeItem(character, item); break; case ItemUsage.Throw: // TODO: throwing range InputManager.Instance.InitiateTargeting((pos) => ThrowItem(character, item, pos)); break; } }
// This function tries to do the following things in order: // tries to use an item if inventory is open // tries to interact with terrain under player // tries to pick up Item private void HandleSpacePressed() { if (UI.InventoryOpen) { //Console.WriteLine("Space trigger item use!"); //Console.WriteLine("UsedItemEvent null? " + UsedItemEvent == null); UsedItemEvent?.Invoke(Util.PlayerID, EntityManager.GetComponent <InventoryComponent>(Util.PlayerID).Items[UI.InventoryCursorPosition - 1], ItemUsage.Consume); return; } var playerPos = EntityManager.GetComponent <TransformComponent>(Util.PlayerID).Position; int terrain = Util.CurrentFloor.GetTerrain(playerPos); if (terrain != 0) // is there special terrain? { var terrainInteraction = EntityManager.GetComponent <InteractableComponent>(terrain); if (terrainInteraction != null) // is it interactable? { InteractionEvent?.Invoke(Util.PlayerID, terrain); return; } } bool itemsOnFloor = Util.CurrentFloor.GetItems(playerPos).Count() > 0; // are there items here? if (!itemsOnFloor) { UISystem.Message("No items here to be picked up!"); return; } PickupItemEvent?.Invoke(Util.PlayerID); }
void HandleAttackMessage(int attacker, int defender, Dictionary <DamageType, int> damages) { var posAttacker = EntityManager.GetComponent <TransformComponent>(attacker).Position; var posDefender = EntityManager.GetComponent <TransformComponent>(defender).Position; var seenPositions = Util.CurrentFloor.GetSeenPositions(); bool attackerVisible = seenPositions.Contains(posAttacker); bool defenderVisible = seenPositions.Contains(posDefender); if (!(attackerVisible || defenderVisible)) { return; } StringBuilder sb = new StringBuilder(); if (attackerVisible) { sb.Append(DescriptionSystem.GetName(attacker)); } else { sb.Append("Something"); } sb.Append(" attacks "); if (defenderVisible) { sb.Append(DescriptionSystem.GetName(defender)); } else { sb.Append("Something"); } sb.Append("!"); // e.g. "(69 fire, 42 water, ...)" sb.Append(" ("); for (int i = 0; i < damages.Count; i++) { if (i > 0) { sb.Append(", "); } sb.AppendFormat("{0} {1}", damages.ElementAt(i).Value, damages.ElementAt(i).Key); } sb.Append(")"); UISystem.Message(sb.ToString()); }
public void ConsumeItem(int character, int item) { UISystem.Message(String.Format("{0} consumes {1}", DescriptionSystem.GetNameWithID(character), DescriptionSystem.GetNameWithID(item))); ApplySubstance(character, item, 1f); IdentifyItem(item); DecreaseItemCount(character, item); TryDeleteItem(item); Util.TurnOver(character); }
public void ChangeStat(int entity, Stat stat, int amount, int duration) { var stats = EntityManager.GetComponent <StatComponent>(entity); if (stats == null) { Log.Warning("This entity doesn't have stats!"); return; } var baseStats = stats.Values; if (duration < 0) { Log.Warning("Stat modification duration can't be smaller than zero!"); return; } if (duration == 0) // permanent! { baseStats[stat] += amount; UISystem.Message("Some attributes of " + DescriptionSystem.GetName(entity) + " have changed! (permanent)"); return; } // add modifications to stats and add to dict for tracking baseStats[stat] += amount; var mod = new StatModification(stat, amount, duration + 1); // add one to duration to compensate for turn of use modifications.TryGetValue(entity, out List <StatModification> modsOfEntity); if (modsOfEntity == null) { //Console.WriteLine("No mod list for this entiy yet"); modsOfEntity = new List <StatModification>() { mod }; modifications.Add(entity, modsOfEntity); } else { modsOfEntity.Add(mod); } UISystem.Message("Some attributes of " + DescriptionSystem.GetName(entity) + " have changed! (" + duration + " turns)"); }
public void HandleLostHealth(int entity, float amountLost) { var healthComponent = EntityManager.GetComponent <HealthComponent>(entity); healthComponent.Amount -= amountLost; // ded if (healthComponent.Amount <= 0) { UISystem.Message(DescriptionSystem.GetNameWithID(entity) + " dies!"); Util.CurrentFloor.RemoveCharacter(LocationSystem.GetPosition(entity)); EntityManager.RemoveEntity(entity); // mark entity for deletion } //Log.Message("Entity " + entity + " HP: " + healthComponent.Amount + "|" + healthComponent.Max + " (-" + amountLost + ")"); }
/// <summary> /// Crafts an item from the added ingredients /// </summary> /// <returns>true if item was succesfully created</returns> public bool CraftItem() { if (items.Count < 2) { UISystem.Message("You need to put in at least two items!"); ResetCrafting(); return(false); } ExtractSubstances(); // TODO: other crafting than alchemy int newItem = Alchemy(); if (newItem == 0) { // something went wrong before and // should have already been handled ResetCrafting(); return(false); } UISystem.Message("You just crafted something!"); substances.Clear(); foreach (var itemID in items) { ItemSystem.TryDeleteItem(itemID); } items.Clear(); //var description = EntityManager.GetComponent<DescriptionComponent>(newItem); //description.Name = "Crafted " + description.Name; ItemAddedEvent?.Invoke(Util.PlayerID, newItem); string info = DescriptionSystem.GetDebugInfoEntity(newItem); Log.Message("Crafting successful:"); Log.Data(info); Util.TurnOver(Util.PlayerID); return(true); }
public void TurnOver(int entity) { modifications.TryGetValue(entity, out List <StatModification> modsOfEntity); if (modsOfEntity == null) { return; } // unless the entity got its stat component removed this should never be null var statsOfEntity = EntityManager.GetComponent <StatComponent>(entity); var stats = statsOfEntity.Values; bool effectRemoved = false; List <StatModification> toBeRemoved = new List <StatModification>(); for (int i = 0; i < modsOfEntity.Count; i++) { var mod = modsOfEntity[i]; mod.Duration -= 1; //Console.WriteLine(mod.Duration + " left"); if (mod.Duration == 0) { // reverse modification and mark for removal stats[mod.Stat] -= mod.Amount; toBeRemoved.Add(mod); effectRemoved = true; } } foreach (var mod in toBeRemoved) { modsOfEntity.Remove(mod); } if (effectRemoved) { UISystem.Message("Some attributes of " + DescriptionSystem.GetName(entity) + " return to normal."); } }
/// <summary> /// try to craft something using alchemy /// assumes all the substances are already extracted /// </summary> /// <returns> ID of newly crafted item (or 0 on fail) </returns> public int Alchemy() { // TODO: check if there's at least some liquid in the recipe or something if (!substances.Any(s => s.MaterialType == Components.MaterialType.Potion)) { UISystem.Message("You need at least one Potion!"); return(0); } Dictionary <Property, int> accumulatedProperties = new Dictionary <Property, int>(); foreach (var substance in substances) { foreach (var prop in substance.Properties) { if (accumulatedProperties.ContainsKey(prop.Key)) { accumulatedProperties[prop.Key] += prop.Value; // TODO: reduce weight of ingredients? } else { accumulatedProperties[prop.Key] = prop.Value; } } } int potion = CreatePotion(accumulatedProperties); // let the player learn about the created potion's properties var knowledge = EntityManager.GetComponent <SubstanceKnowledgeComponent>(Util.PlayerID); foreach (var prop in accumulatedProperties.Keys) { knowledge.PropertyKnowledge[prop] += 10; knowledge.TypeKnowledge[prop.GetPropType()] += 5; } // make sure the properties of the created potion aren't displayed by default EntityManager.GetComponent <SubstanceComponent>(potion).PropertiesKnown = false; return(potion); }
public void AddIngredient(int item) { if (items.Count >= maxSlots) { UISystem.Message("You can't use that many ingredients at once! (max. " + maxSlots + ")"); return; } var substance = EntityManager.GetComponent <SubstanceComponent>(item); if (substance == null) { UISystem.Message("This item can not be used for crafting!"); return; } // remember item and remove it from player inventory items.Add(item); ItemSystem.DecreaseItemCount(Util.PlayerID, item); }
void ApplySubstance(int target, int item, float modifier) { var substance = EntityManager.GetComponent <SubstanceComponent>(item); if (substance == null) { Log.Warning("Usable Item does not have SubstanceComponent attached!"); return; } Dictionary <Property, int> properties = substance.Properties; if (properties == null || properties.Count == 0) { UISystem.Message("That had no effect..."); return; } foreach (var prop in properties) { ResolveProperty(prop.Key, (int)Math.Round(prop.Value * modifier), target); } }
public bool HandleInteraction(int actor, int other) { var interactable = EntityManager.GetComponent <InteractableComponent>(other); if (interactable == null) { Log.Error("HandleInteraction called on non-interactable object!"); Log.Data(DescriptionSystem.GetDebugInfoEntity(other)); return(false); } //Log.Message("Interaction between " + DescriptionSystem.GetNameWithID(actor) + " and " + DescriptionSystem.GetNameWithID(other)); //Log.Data(DescriptionSystem.GetDebugInfoEntity(other)); if (interactable.ChangeSolidity) { var collider = EntityManager.GetComponent <ColliderComponent>(other); if (collider == null) { Log.Warning("Interactable has ChangeSolidity set but has no collider attached! " + DescriptionSystem.GetNameWithID(other)); Log.Data(DescriptionSystem.GetDebugInfoEntity(other)); } else if (collider.Solid == false) { //TODO: make it solid again? ( ._.)? } else { collider.Solid = false; } } if (interactable.ChangeTexture) { var renderable = EntityManager.GetComponent <RenderableSpriteComponent>(other); if (renderable == null) { Log.Error("Interactable has ChangeTexture set but does not have RenderableSprite attached! " + DescriptionSystem.GetNameWithID(other)); Log.Data(DescriptionSystem.GetDebugInfoEntity(other)); return(false); } if (interactable.AlternateTexture == "") { Log.Warning("Interactable has ChangeTexture set but does not define AlternateTexture! " + DescriptionSystem.GetNameWithID(other)); Log.Data(DescriptionSystem.GetDebugInfoEntity(other)); renderable.Texture = "square"; // placholder; something's not right } else { renderable.Texture = interactable.AlternateTexture; } } if (interactable.GrantsItems) { if (interactable.Items == null) { Log.Warning("Interactable has GrantItems set but does not define Items! " + DescriptionSystem.GetNameWithID(other)); Log.Data(DescriptionSystem.GetDebugInfoEntity(other)); } else if (interactable.Items.Count == 0) { UISystem.Message("Nothing here to be picked up!"); return(false); } else { var inventory = EntityManager.GetComponent <InventoryComponent>(actor); if (inventory == null) { Log.Warning("Pick up failed. Character has no inventory! " + DescriptionSystem.GetNameWithID(actor)); return(false); } else { if (ItemAddedEvent == null) { Log.Error("InteractionSystem->ItemAddedEvent is null!"); return(false); } bool success = ItemAddedEvent.Invoke(actor, interactable.Items[0]); if (success) { interactable.Items.RemoveAt(0); } else { // Failed to add to inventory (should already be handled) return(false); } } } } Util.TurnOver(actor); return(true); }
/// <summary> /// tries to add an item to the character's inventory /// </summary> /// <param name="character"></param> /// <param name="item"></param> /// <returns>true on success</returns> public bool AddItem(int character, int item) { var inventory = EntityManager.GetComponent <InventoryComponent>(character); if (inventory == null) { Log.Warning("Character does not have an inventory! -> " + DescriptionSystem.GetNameWithID(character)); return(false); } var itemInfo = EntityManager.GetComponent <ItemComponent>(item); if (itemInfo == null) { Log.Error("Trying to add item entity to character that's not an item!"); Log.Data(DescriptionSystem.GetDescription(item)); return(false); } if (itemInfo.Count == 0) // happens if item comes back from e.g. crafting reset { itemInfo.Count = 1; } // "Re-Stacking" - item gets handed back from e.g. crafting reset if (inventory.Items.Contains(item)) { itemInfo.Count++; return(true); } #region ItemStacking IEnumerable <IComponent> newItem = EntityManager.GetComponents(item); foreach (var inventoryItemID in inventory.Items) { var inventoryItem = EntityManager.GetComponents(inventoryItemID); bool itemMatch = true; foreach (var newItemComponent in newItem) { bool componentMatch = false; if (newItemComponent.TypeID == Component <TransformComponent> .TypeID) { continue; } foreach (var inventoryItemComponent in inventoryItem) { if (newItemComponent.Equals(inventoryItemComponent)) { componentMatch = true; break; } } if (!componentMatch) { itemMatch = false; break; } } if (itemMatch == true) { var invItemInfo = EntityManager.GetComponent <ItemComponent>(inventoryItemID); int newCount = invItemInfo.Count + itemInfo.Count; invItemInfo.Count = Math.Min(newCount, invItemInfo.MaxCount); int itemsLeft = Math.Max(0, newCount - invItemInfo.MaxCount); // TODO: implement overflow if (itemsLeft > 0) { UISystem.Message(String.Format("{0} x{1} was lost in the void...", DescriptionSystem.GetName(item), itemsLeft)); } EntityManager.RemoveEntity(item); return(true); } } // at this point, no matching item was found if (inventory.Full) { UISystem.Message("Inventory is full! -> " + DescriptionSystem.GetNameWithID(character)); return(false); } inventory.Items.Add(item); return(true); #endregion /* * var pickupComponentTypeIDs = EntityManager.GetComponentTypeIDs(item); * * bool match = false; // can item can be stacked here * * // start looking through every item in inventory * // to find out if picked up item can be stacked * foreach (var invItemID in inventory.Items) * { * var invItemInfo = EntityManager.GetComponent<ItemComponent>(invItemID); * * // if already stacked to max, jump straight to next * if (invItemInfo.Count == invItemInfo.MaxCount) * { * match = false; * continue; * } * * var invItemComponentIDs = EntityManager.GetComponentTypeIDs(invItemID); * * // check if both items have the exact same components attached * match = invItemComponentIDs.All(pickupComponentTypeIDs.Contains) && invItemComponentIDs.Count() == pickupComponentTypeIDs.Count(); * * if (match) * { * var pickedUpItemInfo = EntityManager.GetComponent<ItemComponent>(item); * * // cumulative count doesnt exceed max -> just increase count * // in inventory and remove picked up item * if (invItemInfo.Count + pickedUpItemInfo.Count <= invItemInfo.MaxCount) * { * invItemInfo.Count += pickedUpItemInfo.Count; * EntityManager.RemoveEntity(item); * } * * // cumulative count exceeds max -> * // stack up to max, rest becomes new stack * else * { * pickedUpItemInfo.Count -= invItemInfo.MaxCount - invItemInfo.Count; // remove difference used to max out inventory item * invItemInfo.Count = invItemInfo.MaxCount; * inventory.Items.Add(item); * } * break; * } * } */ //if (!match) //{ //} }
/// <summary> /// checks if moving onto newPos is possible /// and triggers any interaction otherwise /// </summary> /// <param name="entity">ID of entity to move</param> /// <param name="newPos">new Position to move to</param> /// <returns>wether movement is possible</returns> private bool TryMove(int entity, Position newPos) { var floor = Util.CurrentFloor; if (floor.IsOutOfBounds(newPos)) { return(false); } int otherCharacter = floor.GetCharacter(newPos); //check if someone's already there if (otherCharacter != 0 && otherCharacter != entity) { // check if collidable if (EntityManager.GetComponent <ColliderComponent>(otherCharacter) != null) { //TODO: talk to npcs? RaiseBasicAttackEvent(entity, otherCharacter); return(false); } else { Log.Warning("Character without collider:"); Log.Data(DescriptionSystem.GetDebugInfoEntity(otherCharacter)); UISystem.Message("Something seems to be there..."); return(false); } } int structure = floor.GetStructure(newPos); if (structure != 0 && EntityManager.GetComponent <ColliderComponent>(structure) != null) { bool solid = RaiseCollisionEvent(entity, structure); // check if interactable var interactable = EntityManager.GetComponent <InteractableComponent>(structure); // only interact with structures right away if they're solid ("bumping" into them) if (solid) { if (interactable != null) { RaiseInteractionEvent(entity, structure); } return(false); } } int terrain = floor.GetTerrain(newPos); // check if collidable with if (terrain != 0 && EntityManager.GetComponent <ColliderComponent>(terrain) != null) { // check if terrain is solid before possible interaction // this is because solidity might be changed by interaction (e.g. door gets opened) bool solid = RaiseCollisionEvent(entity, terrain); // check if interactable var interactable = EntityManager.GetComponent <InteractableComponent>(terrain); if (interactable != null) { RaiseInteractionEvent(entity, terrain); } // check if terrain is solid if (solid) { return(false); } } //trigger special Message on step on if (entity == Util.PlayerID && terrain != 0) { string message = (DescriptionSystem.GetSpecialMessage(terrain, DescriptionComponent.MessageType.StepOn)); if (message.Length > 0) { UISystem.Message(message); } } return(true); }