forked from SoDOff-Project/sodoff
dragons tactics (battle) backpack (#26)
* return battle item as battle items placeholder - no saved stats, always use default stats * Blacksmith API implementation * ApplyRewards (DT rewards) and AddBattleItems also temporary disable some AchievementsTask rewards from DT ... probably should not be repeatable ... * support "box tickets" blueprints - add OpenBox in ItemService (should be useful for other boxes also) - move checking item category to ItemService (ItemHasCategory) * InventoryService and full DragonTactics rewards - move "add to inventory" to InventoryService - move creating CommonInventoryData from inventory to InventoryService - move CreateItemStats() to ItemService - assigning random "item" reward from DT based on dtrewards.xml (at this moment list of all DT items not listed in store) - rework dragon XP and add player XP and gems reward to DT
This commit is contained in:
parent
abe674ccf8
commit
7bee6c620a
@ -79,6 +79,9 @@ Then run School of Dragons.
|
|||||||
- SetAchievementAndGetReward
|
- SetAchievementAndGetReward
|
||||||
- GetAchievementsByUserID
|
- GetAchievementsByUserID
|
||||||
- GetPetAchievementsByUserID
|
- GetPetAchievementsByUserID
|
||||||
|
- RerollUserItem
|
||||||
|
- FuseItems
|
||||||
|
- AddBattleItems
|
||||||
|
|
||||||
#### Implemented enough (probably)
|
#### Implemented enough (probably)
|
||||||
- GetRules (doesn't return any rules, probably doesn't need to)
|
- GetRules (doesn't return any rules, probably doesn't need to)
|
||||||
@ -101,6 +104,8 @@ Then run School of Dragons.
|
|||||||
- SetNextItemState (may require more work, we don't know yet)
|
- SetNextItemState (may require more work, we don't know yet)
|
||||||
- SetUserRoom
|
- SetUserRoom
|
||||||
- SetUserAchievementTask (returns a real reward but still use task placeholder)
|
- SetUserAchievementTask (returns a real reward but still use task placeholder)
|
||||||
|
- SellItems (need add cash reward)
|
||||||
|
- ApplyRewards
|
||||||
|
|
||||||
#### Currently static or stubbed
|
#### Currently static or stubbed
|
||||||
- GetAllRanks (needs to be populated with what ranks the user has)
|
- GetAllRanks (needs to be populated with what ranks the user has)
|
||||||
|
@ -70,6 +70,11 @@ methods = [
|
|||||||
'GetUserGameCurrency',
|
'GetUserGameCurrency',
|
||||||
'SetAchievementByEntityIDs',
|
'SetAchievementByEntityIDs',
|
||||||
'UseInventory',
|
'UseInventory',
|
||||||
|
'SellItems',
|
||||||
|
'FuseItems',
|
||||||
|
'RerollUserItem',
|
||||||
|
'AddBattleItems',
|
||||||
|
'ApplyRewards',
|
||||||
'DeleteProfile',
|
'DeleteProfile',
|
||||||
'DeleteAccountNotification',
|
'DeleteAccountNotification',
|
||||||
'SetUserAchievementAndGetReward',
|
'SetUserAchievementAndGetReward',
|
||||||
|
@ -16,13 +16,16 @@ public class ContentController : Controller {
|
|||||||
private MissionService missionService;
|
private MissionService missionService;
|
||||||
private RoomService roomService;
|
private RoomService roomService;
|
||||||
private AchievementService achievementService;
|
private AchievementService achievementService;
|
||||||
public ContentController(DBContext ctx, KeyValueService keyValueService, ItemService itemService, MissionService missionService, RoomService roomService, AchievementService achievementService) {
|
private InventoryService inventoryService;
|
||||||
|
private Random random = new Random();
|
||||||
|
public ContentController(DBContext ctx, KeyValueService keyValueService, ItemService itemService, MissionService missionService, RoomService roomService, AchievementService achievementService, InventoryService inventoryService) {
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
this.keyValueService = keyValueService;
|
this.keyValueService = keyValueService;
|
||||||
this.itemService = itemService;
|
this.itemService = itemService;
|
||||||
this.missionService = missionService;
|
this.missionService = missionService;
|
||||||
this.roomService = roomService;
|
this.roomService = roomService;
|
||||||
this.achievementService = achievementService;
|
this.achievementService = achievementService;
|
||||||
|
this.inventoryService = inventoryService;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
@ -178,40 +181,25 @@ public class ContentController : Controller {
|
|||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<UserItemData> userItemData;
|
||||||
List<UserItemData> userItemData = new();
|
|
||||||
if (viking != null) {
|
if (viking != null) {
|
||||||
List<InventoryItem> items = viking.Inventory.InventoryItems.ToList();
|
return Ok( inventoryService.GetCommonInventoryData(viking) );
|
||||||
foreach (InventoryItem item in items) {
|
|
||||||
if (item.Quantity == 0) continue; // Don't include an item that the viking doesn't have
|
|
||||||
ItemData itemData = itemService.GetItem(item.ItemId);
|
|
||||||
UserItemData uid = new UserItemData {
|
|
||||||
UserInventoryID = item.Id,
|
|
||||||
ItemID = itemData.ItemID,
|
|
||||||
Quantity = item.Quantity,
|
|
||||||
Uses = itemData.Uses,
|
|
||||||
ModifiedDate = new DateTime(DateTime.Now.Ticks),
|
|
||||||
Item = itemData
|
|
||||||
};
|
|
||||||
userItemData.Add(uid);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// TODO: placeholder - return 8 viking slot items
|
// TODO: placeholder - return 8 viking slot items
|
||||||
UserItemData uid = new UserItemData {
|
return Ok(new CommonInventoryData {
|
||||||
UserInventoryID = 0,
|
UserID = Guid.Parse(user.Id),
|
||||||
ItemID = 7971,
|
Item = new UserItemData[] {
|
||||||
Quantity = 8,
|
new UserItemData {
|
||||||
Uses = -1,
|
UserInventoryID = 0,
|
||||||
ModifiedDate = new DateTime(DateTime.Now.Ticks),
|
ItemID = 7971,
|
||||||
Item = itemService.GetItem(7971)
|
Quantity = 8,
|
||||||
};
|
Uses = -1,
|
||||||
userItemData.Add(uid);
|
ModifiedDate = new DateTime(DateTime.Now.Ticks),
|
||||||
|
Item = itemService.GetItem(7971)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(new CommonInventoryData {
|
|
||||||
UserID = Guid.Parse(user is not null ? user.Id : viking.Id),
|
|
||||||
Item = userItemData.ToArray()
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
@ -221,27 +209,7 @@ public class ContentController : Controller {
|
|||||||
Viking? viking = ctx.Sessions.FirstOrDefault(e => e.ApiToken == apiToken)?.Viking;
|
Viking? viking = ctx.Sessions.FirstOrDefault(e => e.ApiToken == apiToken)?.Viking;
|
||||||
if (viking is null || viking.Inventory is null) return Ok();
|
if (viking is null || viking.Inventory is null) return Ok();
|
||||||
|
|
||||||
List<InventoryItem> items = viking.Inventory.InventoryItems.ToList();
|
return Ok(inventoryService.GetCommonInventoryData(viking));
|
||||||
List<UserItemData> userItemData = new();
|
|
||||||
foreach (InventoryItem item in items) {
|
|
||||||
if (item.Quantity == 0) continue; // Don't include an item that the viking doesn't have
|
|
||||||
ItemData itemData = itemService.GetItem(item.ItemId);
|
|
||||||
UserItemData uid = new UserItemData {
|
|
||||||
UserInventoryID = item.Id,
|
|
||||||
ItemID = itemData.ItemID,
|
|
||||||
Quantity = item.Quantity,
|
|
||||||
Uses = itemData.Uses,
|
|
||||||
ModifiedDate = new DateTime(DateTime.Now.Ticks),
|
|
||||||
Item = itemData
|
|
||||||
};
|
|
||||||
userItemData.Add(uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
CommonInventoryData invData = new CommonInventoryData {
|
|
||||||
UserID = Guid.Parse(viking.UserId),
|
|
||||||
Item = userItemData.ToArray()
|
|
||||||
};
|
|
||||||
return Ok(invData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
@ -267,7 +235,7 @@ public class ContentController : Controller {
|
|||||||
foreach (var req in request) {
|
foreach (var req in request) {
|
||||||
if (req.ItemID == 0) continue; // Do not save a null item
|
if (req.ItemID == 0) continue; // Do not save a null item
|
||||||
|
|
||||||
if (IsFarmExpansion((int)req.ItemID)) {
|
if (inventoryService.ItemNeedUniqueInventorySlot((int)req.ItemID)) {
|
||||||
// if req.Quantity < 0 remove unique items
|
// if req.Quantity < 0 remove unique items
|
||||||
for (int i=req.Quantity; i<0; ++i) {
|
for (int i=req.Quantity; i<0; ++i) {
|
||||||
InventoryItem? item = viking.Inventory.InventoryItems.FirstOrDefault(e => e.ItemId == req.ItemID && e.Quantity>0);
|
InventoryItem? item = viking.Inventory.InventoryItems.FirstOrDefault(e => e.ItemId == req.ItemID && e.Quantity>0);
|
||||||
@ -275,32 +243,16 @@ public class ContentController : Controller {
|
|||||||
}
|
}
|
||||||
// if req.Quantity > 0 add unique items
|
// if req.Quantity > 0 add unique items
|
||||||
for (int i=0; i<req.Quantity; ++i) {
|
for (int i=0; i<req.Quantity; ++i) {
|
||||||
InventoryItem item = new InventoryItem { ItemId = (int)req.ItemID, Quantity = 1 };
|
responseItems.Add(
|
||||||
viking.Inventory.InventoryItems.Add(item);
|
inventoryService.AddItemToInventoryAndGetResponse(viking, (int)req.ItemID!, 1)
|
||||||
ctx.SaveChanges(); // We need to get the ID of the newly created item
|
);
|
||||||
responseItems.Add(new CommonInventoryResponseItem {
|
|
||||||
CommonInventoryID = item.Id,
|
|
||||||
ItemID = item.ItemId,
|
|
||||||
Quantity = 0
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
InventoryItem? item = viking.Inventory.InventoryItems.FirstOrDefault(e => e.ItemId == req.ItemID);
|
if (req.Quantity > 0) {
|
||||||
if (item is null) {
|
responseItems.Add(
|
||||||
item = new InventoryItem { ItemId = (int)req.ItemID, Quantity = 0 };
|
inventoryService.AddItemToInventoryAndGetResponse(viking, (int)req.ItemID!, req.Quantity)
|
||||||
viking.Inventory.InventoryItems.Add(item);
|
);
|
||||||
}
|
}
|
||||||
int updateQuantity = 0; // The game expects 0 if quantity got updated by just 1
|
|
||||||
if (req.Quantity > 1)
|
|
||||||
updateQuantity = req.Quantity; // Otherwise it expects the quantity from the request
|
|
||||||
item.Quantity += req.Quantity;
|
|
||||||
ctx.SaveChanges(); // We need to get the ID of the newly created item
|
|
||||||
if (req.Quantity > 0)
|
|
||||||
responseItems.Add(new CommonInventoryResponseItem {
|
|
||||||
CommonInventoryID = item.Id,
|
|
||||||
ItemID = item.ItemId,
|
|
||||||
Quantity = updateQuantity
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -771,20 +723,9 @@ public class ContentController : Controller {
|
|||||||
PurchaseStoreItemRequest request = XmlUtil.DeserializeXml<PurchaseStoreItemRequest>(purchaseItemRequest);
|
PurchaseStoreItemRequest request = XmlUtil.DeserializeXml<PurchaseStoreItemRequest>(purchaseItemRequest);
|
||||||
CommonInventoryResponseItem[] items = new CommonInventoryResponseItem[request.Items.Length];
|
CommonInventoryResponseItem[] items = new CommonInventoryResponseItem[request.Items.Length];
|
||||||
for (int i = 0; i < request.Items.Length; i++) {
|
for (int i = 0; i < request.Items.Length; i++) {
|
||||||
InventoryItem? item = null;
|
items[i] = inventoryService.AddItemToInventoryAndGetResponse(viking, request.Items[i], 1);
|
||||||
if (!IsFarmExpansion(request.Items[i]))
|
// NOTE: The quantity of purchased items is always 0 and the items are instead duplicated in both the request and the response.
|
||||||
item = viking.Inventory.InventoryItems.FirstOrDefault(e => e.ItemId == request.Items[i]);
|
// Call AddItemToInventoryAndGetResponse with Quantity == 1 we get response with quantity == 0.
|
||||||
if (item is null) {
|
|
||||||
item = new InventoryItem { ItemId = request.Items[i], Quantity = 0 };
|
|
||||||
viking.Inventory.InventoryItems.Add(item);
|
|
||||||
}
|
|
||||||
item.Quantity++;
|
|
||||||
ctx.SaveChanges();
|
|
||||||
items[i] = new CommonInventoryResponseItem {
|
|
||||||
CommonInventoryID = item.Id,
|
|
||||||
ItemID = request.Items[i],
|
|
||||||
Quantity = 0 // The quantity of purchased items is always 0 and the items are instead duplicated in both the request and the response
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CommonInventoryResponse response = new CommonInventoryResponse {
|
CommonInventoryResponse response = new CommonInventoryResponse {
|
||||||
@ -811,18 +752,9 @@ public class ContentController : Controller {
|
|||||||
int[] itemIdArr = XmlUtil.DeserializeXml<int[]>(itemIDArrayXml);
|
int[] itemIdArr = XmlUtil.DeserializeXml<int[]>(itemIDArrayXml);
|
||||||
CommonInventoryResponseItem[] items = new CommonInventoryResponseItem[itemIdArr.Length];
|
CommonInventoryResponseItem[] items = new CommonInventoryResponseItem[itemIdArr.Length];
|
||||||
for (int i = 0; i < itemIdArr.Length; i++) {
|
for (int i = 0; i < itemIdArr.Length; i++) {
|
||||||
InventoryItem? item = viking.Inventory.InventoryItems.FirstOrDefault(e => e.ItemId == itemIdArr[i]);
|
items[i] = inventoryService.AddItemToInventoryAndGetResponse(viking, itemIdArr[i], 1);
|
||||||
if (item is null) {
|
// NOTE: The quantity of purchased items is always 0 and the items are instead duplicated in both the request and the response.
|
||||||
item = new InventoryItem { ItemId = itemIdArr[i], Quantity = 0 };
|
// Call AddItemToInventoryAndGetResponse with Quantity == 1 we get response with quantity == 0.
|
||||||
viking.Inventory.InventoryItems.Add(item);
|
|
||||||
}
|
|
||||||
item.Quantity++;
|
|
||||||
ctx.SaveChanges();
|
|
||||||
items[i] = new CommonInventoryResponseItem {
|
|
||||||
CommonInventoryID = item.Id,
|
|
||||||
ItemID = itemIdArr[i],
|
|
||||||
Quantity = 0 // The quantity of purchased items is always 0 and the items are instead duplicated in both the request and the response
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CommonInventoryResponse response = new CommonInventoryResponse {
|
CommonInventoryResponse response = new CommonInventoryResponse {
|
||||||
@ -991,6 +923,310 @@ public class ContentController : Controller {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[Produces("application/xml")]
|
||||||
|
[Route("V2/ContentWebService.asmx/RerollUserItem")]
|
||||||
|
public IActionResult RerollUserItem([FromForm] string apiToken, [FromForm] string request) {
|
||||||
|
Viking? viking = ctx.Sessions.FirstOrDefault(e => e.ApiToken == apiToken)?.Viking;
|
||||||
|
if (viking is null || viking.Inventory is null) return Unauthorized();
|
||||||
|
|
||||||
|
RollUserItemRequest req = XmlUtil.DeserializeXml<RollUserItemRequest>(request);
|
||||||
|
|
||||||
|
// get item
|
||||||
|
InventoryItem? invItem = viking.Inventory.InventoryItems.FirstOrDefault(e => e.Id == req.UserInventoryID);
|
||||||
|
if (invItem is null)
|
||||||
|
return Ok(new RollUserItemResponse { Status = Status.ItemNotFound });
|
||||||
|
|
||||||
|
// get item data and stats
|
||||||
|
ItemData itemData = itemService.GetItem(invItem.ItemId);
|
||||||
|
ItemStatsMap itemStatsMap;
|
||||||
|
if (invItem.StatsSerialized != null) {
|
||||||
|
itemStatsMap = XmlUtil.DeserializeXml<ItemStatsMap>(invItem.StatsSerialized);
|
||||||
|
} else {
|
||||||
|
itemStatsMap = itemData.ItemStatsMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ItemStat> newStats;
|
||||||
|
Status status = Status.Failure;
|
||||||
|
|
||||||
|
// update stats
|
||||||
|
if (req.ItemStatNames != null) {
|
||||||
|
// reroll only one stat (from req.ItemStatNames)
|
||||||
|
newStats = new List<ItemStat>();
|
||||||
|
foreach (string name in req.ItemStatNames) {
|
||||||
|
ItemStat itemStat = itemStatsMap.ItemStats.FirstOrDefault(e => e.Name == name);
|
||||||
|
|
||||||
|
// draw new stats
|
||||||
|
StatRangeMap rangeMap = itemData.PossibleStatsMap.Stats.FirstOrDefault(e => e.ItemStatsID == itemStat.ItemStatID).ItemStatsRangeMaps.FirstOrDefault(e => e.ItemTierID == (int)(itemStatsMap.ItemTier));
|
||||||
|
int newVal = random.Next(rangeMap.StartRange, rangeMap.EndRange+1);
|
||||||
|
|
||||||
|
// check draw results
|
||||||
|
Int32.TryParse(itemStat.Value, out int oldVal);
|
||||||
|
if (newVal > oldVal) {
|
||||||
|
itemStat.Value = newVal.ToString();
|
||||||
|
newStats.Add(itemStat);
|
||||||
|
status = Status.Success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// get shards
|
||||||
|
inventoryService.AddItemToInventory(viking, InventoryService.Shards, -((int)(itemData.ItemRarity) + (int)(itemStatsMap.ItemTier) - 1));
|
||||||
|
} else {
|
||||||
|
// reroll full item
|
||||||
|
newStats = itemService.CreateItemStats(itemData.PossibleStatsMap, (int)itemData.ItemRarity, (int)itemStatsMap.ItemTier);
|
||||||
|
itemStatsMap.ItemStats = newStats.ToArray();
|
||||||
|
status = Status.Success;
|
||||||
|
// get shards
|
||||||
|
int price = 0;
|
||||||
|
switch (itemData.ItemRarity) {
|
||||||
|
case ItemRarity.Common:
|
||||||
|
price = 5;
|
||||||
|
break;
|
||||||
|
case ItemRarity.Rare:
|
||||||
|
price = 7;
|
||||||
|
break;
|
||||||
|
case ItemRarity.Epic:
|
||||||
|
price = 10;
|
||||||
|
break;
|
||||||
|
case ItemRarity.Legendary:
|
||||||
|
price = 20;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (itemStatsMap.ItemTier) {
|
||||||
|
case ItemTier.Tier2:
|
||||||
|
price = (int)Math.Floor(price * 1.5);
|
||||||
|
break;
|
||||||
|
case ItemTier.Tier3:
|
||||||
|
case ItemTier.Tier4:
|
||||||
|
price = price * 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
inventoryService.AddItemToInventory(viking, InventoryService.Shards, -price);
|
||||||
|
}
|
||||||
|
|
||||||
|
// save
|
||||||
|
invItem.StatsSerialized = XmlUtil.SerializeXml(itemStatsMap);
|
||||||
|
ctx.SaveChanges();
|
||||||
|
|
||||||
|
// return results
|
||||||
|
return Ok(new RollUserItemResponse {
|
||||||
|
Status = status,
|
||||||
|
ItemStats = newStats.ToArray() // we need return only updated stats, so can't `= itemStatsMap.ItemStats`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[Produces("application/xml")]
|
||||||
|
[Route("V2/ContentWebService.asmx/FuseItems")]
|
||||||
|
public IActionResult FuseItems([FromForm] string apiToken, [FromForm] string fuseItemsRequest) {
|
||||||
|
Viking? viking = ctx.Sessions.FirstOrDefault(e => e.ApiToken == apiToken)?.Viking;
|
||||||
|
if (viking is null || viking.Inventory is null) return Unauthorized();
|
||||||
|
|
||||||
|
FuseItemsRequest req = XmlUtil.DeserializeXml<FuseItemsRequest>(fuseItemsRequest);
|
||||||
|
|
||||||
|
ItemData blueprintItem;
|
||||||
|
try {
|
||||||
|
blueprintItem = itemService.GetItem(req.BluePrintItemID ?? -1);
|
||||||
|
} catch(System.Collections.Generic.KeyNotFoundException) {
|
||||||
|
return Ok(new FuseItemsResponse { Status = Status.BluePrintItemNotFound });
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: check for blueprintItem.BluePrint.Deductibles and blueprintItem.BluePrint.Ingredients
|
||||||
|
|
||||||
|
// remove items from DeductibleItemInventoryMaps and BluePrintFuseItemMaps
|
||||||
|
foreach (var item in req.DeductibleItemInventoryMaps) {
|
||||||
|
InventoryItem? invItem = viking.Inventory.InventoryItems.FirstOrDefault(e => e.Id == item.UserInventoryID);
|
||||||
|
invItem.Quantity -= item.Quantity;
|
||||||
|
}
|
||||||
|
foreach (var item in req.BluePrintFuseItemMaps) {
|
||||||
|
InventoryItem? invItem = viking.Inventory.InventoryItems.FirstOrDefault(e => e.Id == item.UserInventoryID);
|
||||||
|
viking.Inventory.InventoryItems.Remove(invItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
var resItemList = new List<InventoryItemStatsMap>();
|
||||||
|
foreach (BluePrintSpecification output in blueprintItem.BluePrint.Outputs) {
|
||||||
|
if (output.ItemID is null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// get new item info
|
||||||
|
int newItemId = (int)(output.ItemID);
|
||||||
|
ItemData newItemData = itemService.GetItem(newItemId);
|
||||||
|
|
||||||
|
// check for "box tickets"
|
||||||
|
if (itemService.ItemHasCategory(newItemData, 462)) {
|
||||||
|
newItemId = itemService.OpenBox(newItemData).ItemId;
|
||||||
|
}
|
||||||
|
|
||||||
|
resItemList.Add(
|
||||||
|
inventoryService.AddBattleItemToInventory(viking, newItemId, (int)output.Tier)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// return response with new item info
|
||||||
|
return Ok(new FuseItemsResponse {
|
||||||
|
Status = Status.Success,
|
||||||
|
InventoryItemStatsMaps = resItemList
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[Produces("application/xml")]
|
||||||
|
[Route("V2/ContentWebService.asmx/SellItems")]
|
||||||
|
public IActionResult SellItems([FromForm] string apiToken, [FromForm] string sellItemsRequest) {
|
||||||
|
Viking? viking = ctx.Sessions.FirstOrDefault(e => e.ApiToken == apiToken)?.Viking;
|
||||||
|
if (viking is null || viking.Inventory is null) return Unauthorized();
|
||||||
|
|
||||||
|
int price = 0;
|
||||||
|
SellItemsRequest req = XmlUtil.DeserializeXml<SellItemsRequest>(sellItemsRequest);
|
||||||
|
foreach (var invItemID in req.UserInventoryCommonIDs) {
|
||||||
|
// get item from inventory
|
||||||
|
InventoryItem? item = viking.Inventory.InventoryItems.FirstOrDefault(e => e.Id == invItemID);
|
||||||
|
|
||||||
|
// get item data
|
||||||
|
ItemData? itemData = itemService.GetItem(item.ItemId);
|
||||||
|
|
||||||
|
// calculate price
|
||||||
|
switch (itemData.ItemRarity) {
|
||||||
|
case ItemRarity.Common:
|
||||||
|
price += 1;
|
||||||
|
break;
|
||||||
|
case ItemRarity.Rare:
|
||||||
|
price += 3;
|
||||||
|
break;
|
||||||
|
case ItemRarity.Epic:
|
||||||
|
price += 5;
|
||||||
|
break;
|
||||||
|
case ItemRarity.Legendary:
|
||||||
|
price += 10;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: cash rewards
|
||||||
|
|
||||||
|
// remove item
|
||||||
|
viking.Inventory.InventoryItems.Remove(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
// apply shards reward
|
||||||
|
CommonInventoryResponseItem? resShardsItem = inventoryService.AddItemToInventoryAndGetResponse(viking, InventoryService.Shards, price);
|
||||||
|
|
||||||
|
// save
|
||||||
|
ctx.SaveChanges();
|
||||||
|
|
||||||
|
// return success with shards reward
|
||||||
|
return Ok(new CommonInventoryResponse {
|
||||||
|
Success = true,
|
||||||
|
CommonInventoryIDs = new CommonInventoryResponseItem[] {
|
||||||
|
resShardsItem
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[Produces("application/xml")]
|
||||||
|
[Route("V2/ContentWebService.asmx/AddBattleItems")]
|
||||||
|
public IActionResult AddBattleItems([FromForm] string apiToken, [FromForm] string request) {
|
||||||
|
Viking? viking = ctx.Sessions.FirstOrDefault(e => e.ApiToken == apiToken)?.Viking;
|
||||||
|
if (viking is null || viking.Inventory is null) return Unauthorized();
|
||||||
|
|
||||||
|
AddBattleItemsRequest req = XmlUtil.DeserializeXml<AddBattleItemsRequest>(request);
|
||||||
|
|
||||||
|
var resItemList = new List<InventoryItemStatsMap>();
|
||||||
|
foreach (BattleItemTierMap battleItemTierMap in req.BattleItemTierMaps) {
|
||||||
|
for (int i=0; i<battleItemTierMap.Quantity; ++i) {
|
||||||
|
resItemList.Add(
|
||||||
|
inventoryService.AddBattleItemToInventory(viking, battleItemTierMap.ItemID, (int)battleItemTierMap.Tier, battleItemTierMap.ItemStats)
|
||||||
|
// NOTE: battleItemTierMap.ItemStats is extension for importer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(new AddBattleItemsResponse{
|
||||||
|
Status = Status.Success,
|
||||||
|
InventoryItemStatsMaps = resItemList
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[Produces("application/xml")]
|
||||||
|
[Route("V2/ContentWebService.asmx/ApplyRewards")]
|
||||||
|
public IActionResult ApplyRewards([FromForm] string apiToken, [FromForm] string request) {
|
||||||
|
Viking? viking = ctx.Sessions.FirstOrDefault(e => e.ApiToken == apiToken)?.Viking;
|
||||||
|
if (viking is null || viking.Inventory is null) return Unauthorized();
|
||||||
|
|
||||||
|
ApplyRewardsRequest req = XmlUtil.DeserializeXml<ApplyRewardsRequest>(request);
|
||||||
|
|
||||||
|
List<AchievementReward> achievementRewards = new List<AchievementReward>();
|
||||||
|
UserItemStatsMap rewardedItem = null;
|
||||||
|
CommonInventoryResponse rewardedBlueprint = null;
|
||||||
|
|
||||||
|
int rewardMultipler = 0;
|
||||||
|
if (req.LevelRewardType == LevelRewardType.LevelFailure) {
|
||||||
|
rewardMultipler = 1;
|
||||||
|
} else if (req.LevelRewardType == LevelRewardType.LevelCompletion) {
|
||||||
|
rewardMultipler = 2 * req.LevelDifficultyID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rewardMultipler > 0) {
|
||||||
|
// TODO: XP values and method of calculation is not grounded in anything ...
|
||||||
|
|
||||||
|
// dragons XP
|
||||||
|
int dragonXp = 40 * rewardMultipler;
|
||||||
|
foreach (RaisedPetEntityMap petInfo in req.RaisedPetEntityMaps) {
|
||||||
|
Dragon? dragon = viking.Dragons.FirstOrDefault(e => e.Id == petInfo.RaisedPetID);
|
||||||
|
dragon.PetXP = (dragon.PetXP ?? 0) + dragonXp;
|
||||||
|
achievementRewards.Add(new AchievementReward{
|
||||||
|
EntityID = petInfo.EntityID,
|
||||||
|
PointTypeID = AchievementPointTypes.DragonXP,
|
||||||
|
EntityTypeID = 3, // dragon ?
|
||||||
|
RewardID = 1265, // TODO: placeholder
|
||||||
|
Amount = dragonXp
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// player XP and gems
|
||||||
|
achievementRewards.Add(
|
||||||
|
achievementService.AddAchievementPointsAndGetReward(viking, AchievementPointTypes.PlayerXP, 60 * rewardMultipler)
|
||||||
|
);
|
||||||
|
achievementRewards.Add(
|
||||||
|
achievementService.AddAchievementPointsAndGetReward(viking, AchievementPointTypes.CashCurrency, 2 * rewardMultipler)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - battle backpack items and blueprints
|
||||||
|
if (req.LevelRewardType != LevelRewardType.LevelFailure) {
|
||||||
|
ItemData rewardItem = itemService.GetDTReward();
|
||||||
|
if (itemService.ItemHasCategory(rewardItem, 651)) {
|
||||||
|
// blueprint
|
||||||
|
CommonInventoryResponseItem blueprintItem = inventoryService.AddItemToInventoryAndGetResponse(viking, rewardItem.ItemID, 1);
|
||||||
|
rewardedBlueprint = new CommonInventoryResponse {
|
||||||
|
Success = true,
|
||||||
|
CommonInventoryIDs = new CommonInventoryResponseItem[] {
|
||||||
|
blueprintItem
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// DT item
|
||||||
|
InventoryItemStatsMap item = inventoryService.AddBattleItemToInventory(viking, rewardItem.ItemID, random.Next(1, 4));
|
||||||
|
rewardedItem = new UserItemStatsMap {
|
||||||
|
Item = item.Item,
|
||||||
|
ItemStats = item.ItemStatsMap.ItemStats,
|
||||||
|
ItemTier = item.ItemStatsMap.ItemTier,
|
||||||
|
CreatedDate = new DateTime(DateTime.Now.Ticks)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// save
|
||||||
|
ctx.SaveChanges();
|
||||||
|
|
||||||
|
return Ok(new ApplyRewardsResponse {
|
||||||
|
Status = Status.Success,
|
||||||
|
AchievementRewards = achievementRewards.ToArray(),
|
||||||
|
RewardedItemStatsMap = rewardedItem,
|
||||||
|
CommonInventoryResponse = rewardedBlueprint,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private RaisedPetData GetRaisedPetDataFromDragon (Dragon dragon) {
|
private RaisedPetData GetRaisedPetDataFromDragon (Dragon dragon) {
|
||||||
RaisedPetData data = XmlUtil.DeserializeXml<RaisedPetData>(dragon.RaisedPetData);
|
RaisedPetData data = XmlUtil.DeserializeXml<RaisedPetData>(dragon.RaisedPetData);
|
||||||
data.RaisedPetID = dragon.Id;
|
data.RaisedPetID = dragon.Id;
|
||||||
@ -1062,18 +1298,6 @@ public class ContentController : Controller {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsFarmExpansion(int itemId) {
|
|
||||||
ItemData? itemData = itemService.GetItem(itemId);
|
|
||||||
if (itemData != null && itemData.Category != null) {
|
|
||||||
foreach (ItemDataCategory itemCategory in itemData.Category) {
|
|
||||||
if (itemCategory.CategoryId == 541) { // if item is farm expansion
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddSuggestion(Random rand, string name, List<string> suggestions) {
|
private void AddSuggestion(Random rand, string name, List<string> suggestions) {
|
||||||
if (ctx.Vikings.Any(x => x.Name == name) || suggestions.Contains(name)) {
|
if (ctx.Vikings.Any(x => x.Name == name) || suggestions.Contains(name)) {
|
||||||
name += rand.Next(1, 5000);
|
name += rand.Next(1, 5000);
|
||||||
|
@ -8,6 +8,8 @@ namespace sodoff.Model {
|
|||||||
public int ItemId { get; set; }
|
public int ItemId { get; set; }
|
||||||
|
|
||||||
public int InventoryId { get; set; }
|
public int InventoryId { get; set; }
|
||||||
|
|
||||||
|
public string? StatsSerialized { get; set; }
|
||||||
|
|
||||||
public virtual Inventory Inventory { get; set; }
|
public virtual Inventory Inventory { get; set; }
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ builder.Services.AddScoped<MissionService>();
|
|||||||
builder.Services.AddSingleton<StoreService>();
|
builder.Services.AddSingleton<StoreService>();
|
||||||
builder.Services.AddScoped<RoomService>();
|
builder.Services.AddScoped<RoomService>();
|
||||||
builder.Services.AddSingleton<AchievementService>();
|
builder.Services.AddSingleton<AchievementService>();
|
||||||
|
builder.Services.AddScoped<InventoryService>();
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
|
@ -517,6 +517,8 @@
|
|||||||
</AchievementsTaskInfo>
|
</AchievementsTaskInfo>
|
||||||
<AchievementsTaskInfo>
|
<AchievementsTaskInfo>
|
||||||
<TID>2261</TID>
|
<TID>2261</TID>
|
||||||
|
<!-- defeated enemy in dt -->
|
||||||
|
<!-- TODO: temporary disabled - this probably should not be repeated for every event
|
||||||
<AR>
|
<AR>
|
||||||
<a>300</a>
|
<a>300</a>
|
||||||
<p>1</p>
|
<p>1</p>
|
||||||
@ -537,10 +539,12 @@
|
|||||||
<t>1</t>
|
<t>1</t>
|
||||||
<r>937</r>
|
<r>937</r>
|
||||||
<ii>0</ii>
|
<ii>0</ii>
|
||||||
</AR>
|
</AR> -->
|
||||||
</AchievementsTaskInfo>
|
</AchievementsTaskInfo>
|
||||||
<AchievementsTaskInfo>
|
<AchievementsTaskInfo>
|
||||||
<TID>2262</TID>
|
<TID>2262</TID>
|
||||||
|
<!-- ?? in DT -->
|
||||||
|
<!-- TODO: temporary disabled - this probably should not be repeated for every event
|
||||||
<AR>
|
<AR>
|
||||||
<a>10</a>
|
<a>10</a>
|
||||||
<p>12</p>
|
<p>12</p>
|
||||||
@ -568,7 +572,7 @@
|
|||||||
<t>1</t>
|
<t>1</t>
|
||||||
<r>937</r>
|
<r>937</r>
|
||||||
<ii>0</ii>
|
<ii>0</ii>
|
||||||
</AR>
|
</AR> -->
|
||||||
</AchievementsTaskInfo>
|
</AchievementsTaskInfo>
|
||||||
<AchievementsTaskInfo>
|
<AchievementsTaskInfo>
|
||||||
<TID>2263</TID>
|
<TID>2263</TID>
|
||||||
@ -610,6 +614,7 @@
|
|||||||
</AchievementsTaskInfo>
|
</AchievementsTaskInfo>
|
||||||
<AchievementsTaskInfo>
|
<AchievementsTaskInfo>
|
||||||
<TID>2264</TID>
|
<TID>2264</TID>
|
||||||
|
<!-- ?? in DT -->
|
||||||
<AR>
|
<AR>
|
||||||
<a>100</a>
|
<a>100</a>
|
||||||
<p>1</p>
|
<p>1</p>
|
||||||
@ -658,7 +663,9 @@
|
|||||||
</AchievementsTaskInfo>
|
</AchievementsTaskInfo>
|
||||||
<AchievementsTaskInfo>
|
<AchievementsTaskInfo>
|
||||||
<TID>2267</TID>
|
<TID>2267</TID>
|
||||||
|
<!-- winning DT -->
|
||||||
<!-- can return higher (10 times!) rewards also -->
|
<!-- can return higher (10 times!) rewards also -->
|
||||||
|
<!-- TODO: temporary disabled - this probably should not be repeated for every event
|
||||||
<AR>
|
<AR>
|
||||||
<a>20</a>
|
<a>20</a>
|
||||||
<p>1</p>
|
<p>1</p>
|
||||||
@ -686,11 +693,13 @@
|
|||||||
<t>1</t>
|
<t>1</t>
|
||||||
<r>937</r>
|
<r>937</r>
|
||||||
<ii>0</ii>
|
<ii>0</ii>
|
||||||
</AR>
|
</AR> -->
|
||||||
</AchievementsTaskInfo>
|
</AchievementsTaskInfo>
|
||||||
<AchievementsTaskInfo>
|
<AchievementsTaskInfo>
|
||||||
<TID>2268</TID>
|
<TID>2268</TID>
|
||||||
|
<!-- winning DT -->
|
||||||
<!-- can return higher rewards also, for example 340 dragon XP and 330 player XP -->
|
<!-- can return higher rewards also, for example 340 dragon XP and 330 player XP -->
|
||||||
|
<!-- TODO: temporary disabled - this probably should not be repeated for every event
|
||||||
<AR>
|
<AR>
|
||||||
<a>30</a>
|
<a>30</a>
|
||||||
<p>1</p>
|
<p>1</p>
|
||||||
@ -718,7 +727,11 @@
|
|||||||
<t>1</t>
|
<t>1</t>
|
||||||
<r>937</r>
|
<r>937</r>
|
||||||
<ii>0</ii>
|
<ii>0</ii>
|
||||||
</AR>
|
</AR> -->
|
||||||
|
</AchievementsTaskInfo>
|
||||||
|
<AchievementsTaskInfo>
|
||||||
|
<TID>2269</TID>
|
||||||
|
<!-- losing DT -->
|
||||||
</AchievementsTaskInfo>
|
</AchievementsTaskInfo>
|
||||||
<AchievementsTaskInfo>
|
<AchievementsTaskInfo>
|
||||||
<TID>2275</TID>
|
<TID>2275</TID>
|
||||||
|
309
src/Resources/dtrewards.xml
Normal file
309
src/Resources/dtrewards.xml
Normal file
@ -0,0 +1,309 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ArrayOfInt xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<int>12374</int>
|
||||||
|
<int>12375</int>
|
||||||
|
<int>12377</int>
|
||||||
|
<int>12378</int>
|
||||||
|
<int>12379</int>
|
||||||
|
<int>12380</int>
|
||||||
|
<int>12381</int>
|
||||||
|
<int>12382</int>
|
||||||
|
<int>12383</int>
|
||||||
|
<int>12392</int>
|
||||||
|
<int>12393</int>
|
||||||
|
<int>12394</int>
|
||||||
|
<int>12396</int>
|
||||||
|
<int>12397</int>
|
||||||
|
<int>12398</int>
|
||||||
|
<int>13660</int>
|
||||||
|
<int>13661</int>
|
||||||
|
<int>13684</int>
|
||||||
|
<int>13685</int>
|
||||||
|
<int>13686</int>
|
||||||
|
<int>13687</int>
|
||||||
|
<int>13700</int>
|
||||||
|
<int>13701</int>
|
||||||
|
<int>13718</int>
|
||||||
|
<int>13719</int>
|
||||||
|
<int>13720</int>
|
||||||
|
<int>13721</int>
|
||||||
|
<int>13722</int>
|
||||||
|
<int>13723</int>
|
||||||
|
<int>13724</int>
|
||||||
|
<int>13725</int>
|
||||||
|
<int>13726</int>
|
||||||
|
<int>13727</int>
|
||||||
|
<int>13728</int>
|
||||||
|
<int>13747</int>
|
||||||
|
<int>13748</int>
|
||||||
|
<int>13749</int>
|
||||||
|
<int>13750</int>
|
||||||
|
<int>13751</int>
|
||||||
|
<int>13752</int>
|
||||||
|
<int>13753</int>
|
||||||
|
<int>13754</int>
|
||||||
|
<int>13755</int>
|
||||||
|
<int>13757</int>
|
||||||
|
<int>13758</int>
|
||||||
|
<int>13759</int>
|
||||||
|
<int>13760</int>
|
||||||
|
<int>13761</int>
|
||||||
|
<int>13762</int>
|
||||||
|
<int>13763</int>
|
||||||
|
<int>13764</int>
|
||||||
|
<int>13765</int>
|
||||||
|
<int>13766</int>
|
||||||
|
<int>13767</int>
|
||||||
|
<int>13768</int>
|
||||||
|
<int>13769</int>
|
||||||
|
<int>13770</int>
|
||||||
|
<int>13771</int>
|
||||||
|
<int>13772</int>
|
||||||
|
<int>13773</int>
|
||||||
|
<int>14842</int>
|
||||||
|
<int>14843</int>
|
||||||
|
<int>14844</int>
|
||||||
|
<int>14845</int>
|
||||||
|
<int>14846</int>
|
||||||
|
<int>14847</int>
|
||||||
|
<int>14848</int>
|
||||||
|
<int>14849</int>
|
||||||
|
<int>14850</int>
|
||||||
|
<int>14851</int>
|
||||||
|
<int>14852</int>
|
||||||
|
<int>14853</int>
|
||||||
|
<int>14854</int>
|
||||||
|
<int>14855</int>
|
||||||
|
<int>14856</int>
|
||||||
|
<int>14857</int>
|
||||||
|
<int>14858</int>
|
||||||
|
<int>14859</int>
|
||||||
|
<int>14860</int>
|
||||||
|
<int>14861</int>
|
||||||
|
<int>14862</int>
|
||||||
|
<int>14863</int>
|
||||||
|
<int>14864</int>
|
||||||
|
<int>14865</int>
|
||||||
|
<int>14866</int>
|
||||||
|
<int>14867</int>
|
||||||
|
<int>14868</int>
|
||||||
|
<int>14869</int>
|
||||||
|
<int>14870</int>
|
||||||
|
<int>14871</int>
|
||||||
|
<int>14873</int>
|
||||||
|
<int>14874</int>
|
||||||
|
<int>14875</int>
|
||||||
|
<int>14876</int>
|
||||||
|
<int>14877</int>
|
||||||
|
<int>14878</int>
|
||||||
|
<int>14879</int>
|
||||||
|
<int>14880</int>
|
||||||
|
<int>14881</int>
|
||||||
|
<int>14882</int>
|
||||||
|
<int>14883</int>
|
||||||
|
<int>14908</int>
|
||||||
|
<int>14921</int>
|
||||||
|
<int>14923</int>
|
||||||
|
<int>14933</int>
|
||||||
|
<int>15778</int>
|
||||||
|
<int>15781</int>
|
||||||
|
<int>15784</int>
|
||||||
|
<int>15785</int>
|
||||||
|
<int>15899</int>
|
||||||
|
<int>16249</int>
|
||||||
|
<int>16669</int>
|
||||||
|
<int>16670</int>
|
||||||
|
<int>16671</int>
|
||||||
|
<int>16729</int>
|
||||||
|
<int>16730</int>
|
||||||
|
<int>16731</int>
|
||||||
|
<int>16735</int>
|
||||||
|
<int>16806</int>
|
||||||
|
<int>17864</int>
|
||||||
|
<int>17865</int>
|
||||||
|
<int>17885</int>
|
||||||
|
<int>17886</int>
|
||||||
|
<int>17943</int>
|
||||||
|
<int>17997</int>
|
||||||
|
<int>18064</int>
|
||||||
|
<int>18099</int>
|
||||||
|
<int>18111</int>
|
||||||
|
<int>18274</int>
|
||||||
|
<int>18276</int>
|
||||||
|
<int>18278</int>
|
||||||
|
<int>18289</int>
|
||||||
|
<int>18290</int>
|
||||||
|
<int>18291</int>
|
||||||
|
<int>18339</int>
|
||||||
|
<int>18340</int>
|
||||||
|
<int>18467</int>
|
||||||
|
<int>18468</int>
|
||||||
|
<int>18482</int>
|
||||||
|
<int>18483</int>
|
||||||
|
<int>18489</int>
|
||||||
|
<int>18490</int>
|
||||||
|
<int>18491</int>
|
||||||
|
<int>18492</int>
|
||||||
|
<int>18493</int>
|
||||||
|
<int>18494</int>
|
||||||
|
<int>18495</int>
|
||||||
|
<int>18496</int>
|
||||||
|
<int>18497</int>
|
||||||
|
<int>18498</int>
|
||||||
|
<int>18501</int>
|
||||||
|
<int>18751</int>
|
||||||
|
<int>18752</int>
|
||||||
|
<int>18779</int>
|
||||||
|
<int>18780</int>
|
||||||
|
<int>18781</int>
|
||||||
|
<int>18782</int>
|
||||||
|
<int>18783</int>
|
||||||
|
<int>18784</int>
|
||||||
|
<int>18785</int>
|
||||||
|
<int>18812</int>
|
||||||
|
<int>18813</int>
|
||||||
|
<int>18814</int>
|
||||||
|
<int>19002</int>
|
||||||
|
<int>19021</int>
|
||||||
|
<int>19022</int>
|
||||||
|
<int>19023</int>
|
||||||
|
<int>19024</int>
|
||||||
|
<int>19025</int>
|
||||||
|
<int>19026</int>
|
||||||
|
<int>19027</int>
|
||||||
|
<int>19028</int>
|
||||||
|
<int>19029</int>
|
||||||
|
<int>19030</int>
|
||||||
|
<int>19046</int>
|
||||||
|
<int>19047</int>
|
||||||
|
<int>19112</int>
|
||||||
|
<int>19113</int>
|
||||||
|
<int>19181</int>
|
||||||
|
<int>20261</int>
|
||||||
|
<int>20262</int>
|
||||||
|
<int>20263</int>
|
||||||
|
<int>20304</int>
|
||||||
|
<int>20476</int>
|
||||||
|
<int>20477</int>
|
||||||
|
<int>20478</int>
|
||||||
|
<int>20492</int>
|
||||||
|
<int>20493</int>
|
||||||
|
<int>20496</int>
|
||||||
|
<int>20497</int>
|
||||||
|
<int>20498</int>
|
||||||
|
<int>20499</int>
|
||||||
|
<int>20500</int>
|
||||||
|
<int>20501</int>
|
||||||
|
<int>20502</int>
|
||||||
|
<int>20503</int>
|
||||||
|
<int>20504</int>
|
||||||
|
<int>20505</int>
|
||||||
|
<int>20506</int>
|
||||||
|
<int>20507</int>
|
||||||
|
<int>20508</int>
|
||||||
|
<int>20509</int>
|
||||||
|
<int>20510</int>
|
||||||
|
<int>20511</int>
|
||||||
|
<int>20512</int>
|
||||||
|
<int>20513</int>
|
||||||
|
<int>20515</int>
|
||||||
|
<int>20516</int>
|
||||||
|
<int>20517</int>
|
||||||
|
<int>20518</int>
|
||||||
|
<int>20519</int>
|
||||||
|
<int>20520</int>
|
||||||
|
<int>20521</int>
|
||||||
|
<int>20522</int>
|
||||||
|
<int>20523</int>
|
||||||
|
<int>20524</int>
|
||||||
|
<int>20525</int>
|
||||||
|
<int>20526</int>
|
||||||
|
<int>20527</int>
|
||||||
|
<int>20528</int>
|
||||||
|
<int>20529</int>
|
||||||
|
<int>20530</int>
|
||||||
|
<int>20531</int>
|
||||||
|
<int>20532</int>
|
||||||
|
<int>20533</int>
|
||||||
|
<int>20534</int>
|
||||||
|
<int>20535</int>
|
||||||
|
<int>20536</int>
|
||||||
|
<int>20537</int>
|
||||||
|
<int>20538</int>
|
||||||
|
<int>20539</int>
|
||||||
|
<int>20540</int>
|
||||||
|
<int>20541</int>
|
||||||
|
<int>20542</int>
|
||||||
|
<int>20543</int>
|
||||||
|
<int>20544</int>
|
||||||
|
<int>20545</int>
|
||||||
|
<int>20546</int>
|
||||||
|
<int>20547</int>
|
||||||
|
<int>20548</int>
|
||||||
|
<int>20549</int>
|
||||||
|
<int>20550</int>
|
||||||
|
<int>20551</int>
|
||||||
|
<int>20552</int>
|
||||||
|
<int>20553</int>
|
||||||
|
<int>20554</int>
|
||||||
|
<int>20555</int>
|
||||||
|
<int>20556</int>
|
||||||
|
<int>20557</int>
|
||||||
|
<int>20558</int>
|
||||||
|
<int>20559</int>
|
||||||
|
<int>20560</int>
|
||||||
|
<int>20561</int>
|
||||||
|
<int>20562</int>
|
||||||
|
<int>20563</int>
|
||||||
|
<int>20564</int>
|
||||||
|
<int>20565</int>
|
||||||
|
<int>20566</int>
|
||||||
|
<int>20567</int>
|
||||||
|
<int>20568</int>
|
||||||
|
<int>20569</int>
|
||||||
|
<int>20570</int>
|
||||||
|
<int>20571</int>
|
||||||
|
<int>20572</int>
|
||||||
|
<int>20573</int>
|
||||||
|
<int>20574</int>
|
||||||
|
<int>20575</int>
|
||||||
|
<int>20576</int>
|
||||||
|
<int>20577</int>
|
||||||
|
<int>20578</int>
|
||||||
|
<int>20579</int>
|
||||||
|
<int>20580</int>
|
||||||
|
<int>20581</int>
|
||||||
|
<int>20582</int>
|
||||||
|
<int>20583</int>
|
||||||
|
<int>20584</int>
|
||||||
|
<int>20585</int>
|
||||||
|
<int>20586</int>
|
||||||
|
<int>20587</int>
|
||||||
|
<int>20588</int>
|
||||||
|
<int>20589</int>
|
||||||
|
<int>20590</int>
|
||||||
|
<int>20591</int>
|
||||||
|
<int>20592</int>
|
||||||
|
<int>20593</int>
|
||||||
|
<int>20594</int>
|
||||||
|
<int>20595</int>
|
||||||
|
<int>20596</int>
|
||||||
|
<int>20597</int>
|
||||||
|
<int>20598</int>
|
||||||
|
<int>20599</int>
|
||||||
|
<int>20600</int>
|
||||||
|
<int>20601</int>
|
||||||
|
<int>20602</int>
|
||||||
|
<int>20603</int>
|
||||||
|
<int>20604</int>
|
||||||
|
<int>20605</int>
|
||||||
|
<int>20606</int>
|
||||||
|
<int>20607</int>
|
||||||
|
<int>20608</int>
|
||||||
|
<int>20609</int>
|
||||||
|
<int>20610</int>
|
||||||
|
<int>20857</int>
|
||||||
|
<int>20858</int>
|
||||||
|
<int>7149</int>
|
||||||
|
<int>7150</int>
|
||||||
|
</ArrayOfInt>
|
10
src/Schema/AddBattleItemsRequest.cs
Normal file
10
src/Schema/AddBattleItemsRequest.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace sodoff.Schema;
|
||||||
|
|
||||||
|
[XmlRoot(ElementName = "ABIR", Namespace = "")]
|
||||||
|
[Serializable]
|
||||||
|
public class AddBattleItemsRequest {
|
||||||
|
[XmlElement(ElementName = "BITM", IsNullable = false)]
|
||||||
|
public List<BattleItemTierMap> BattleItemTierMaps { get; set; }
|
||||||
|
}
|
13
src/Schema/AddBattleItemsResponse.cs
Normal file
13
src/Schema/AddBattleItemsResponse.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace sodoff.Schema;
|
||||||
|
|
||||||
|
[XmlRoot(ElementName = "ABIRES", Namespace = "")]
|
||||||
|
[Serializable]
|
||||||
|
public class AddBattleItemsResponse {
|
||||||
|
[XmlElement(ElementName = "ST", IsNullable = false)]
|
||||||
|
public Status Status { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "IISM", IsNullable = true)]
|
||||||
|
public List<InventoryItemStatsMap> InventoryItemStatsMaps { get; set; }
|
||||||
|
}
|
28
src/Schema/ApplyRewardsRequest.cs
Normal file
28
src/Schema/ApplyRewardsRequest.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace sodoff.Schema;
|
||||||
|
|
||||||
|
[XmlRoot(ElementName = "ARRES", IsNullable = true)]
|
||||||
|
[Serializable]
|
||||||
|
public class ApplyRewardsRequest {
|
||||||
|
[XmlElement(ElementName = "GID", IsNullable = false)]
|
||||||
|
public int GameID { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "LID", IsNullable = false)]
|
||||||
|
public int LevelID { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "LDID", IsNullable = false)]
|
||||||
|
public int LevelDifficultyID { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "LRT", IsNullable = false)]
|
||||||
|
public LevelRewardType LevelRewardType { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "RPEMS", IsNullable = false)]
|
||||||
|
public RaisedPetEntityMap[] RaisedPetEntityMaps { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "AGN", IsNullable = false)]
|
||||||
|
public Gender AvatarGender { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "LOC", IsNullable = true)]
|
||||||
|
public string Locale { get; set; }
|
||||||
|
}
|
22
src/Schema/ApplyRewardsResponse.cs
Normal file
22
src/Schema/ApplyRewardsResponse.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace sodoff.Schema;
|
||||||
|
|
||||||
|
[XmlRoot(ElementName = "ARR", Namespace = "")]
|
||||||
|
[Serializable]
|
||||||
|
public class ApplyRewardsResponse {
|
||||||
|
[XmlElement(ElementName = "ST", IsNullable = false)]
|
||||||
|
public Status Status { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "UID", IsNullable = false)]
|
||||||
|
public Guid UserID { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "ARS", IsNullable = false)]
|
||||||
|
public AchievementReward[] AchievementRewards { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "RISM", IsNullable = true)]
|
||||||
|
public UserItemStatsMap RewardedItemStatsMap { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "CIR", IsNullable = true)]
|
||||||
|
public CommonInventoryResponse CommonInventoryResponse { get; set; }
|
||||||
|
}
|
19
src/Schema/BattleItemTierMap.cs
Normal file
19
src/Schema/BattleItemTierMap.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace sodoff.Schema;
|
||||||
|
|
||||||
|
[XmlRoot(ElementName = "BITM", Namespace = "")]
|
||||||
|
[Serializable]
|
||||||
|
public class BattleItemTierMap {
|
||||||
|
[XmlElement(ElementName = "IID", IsNullable = false)]
|
||||||
|
public int ItemID { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "T", IsNullable = true)]
|
||||||
|
public ItemTier? Tier { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "QTY", IsNullable = true)]
|
||||||
|
public int? Quantity { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "iss", IsNullable = true)]
|
||||||
|
public ItemStat[] ItemStats { get; set; }
|
||||||
|
}
|
13
src/Schema/BluePrintFuseItemMap.cs
Normal file
13
src/Schema/BluePrintFuseItemMap.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace sodoff.Schema;
|
||||||
|
|
||||||
|
[XmlRoot(ElementName = "BPFIM", Namespace = "")]
|
||||||
|
[Serializable]
|
||||||
|
public class BluePrintFuseItemMap {
|
||||||
|
[XmlElement(ElementName = "BPSID", IsNullable = false)]
|
||||||
|
public int BluePrintSpecID { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "UID", IsNullable = false)]
|
||||||
|
public int UserInventoryID { get; set; }
|
||||||
|
}
|
16
src/Schema/DeductibleItemInventoryMap.cs
Normal file
16
src/Schema/DeductibleItemInventoryMap.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace sodoff.Schema;
|
||||||
|
|
||||||
|
[XmlRoot(ElementName = "DIIM", Namespace = "")]
|
||||||
|
[Serializable]
|
||||||
|
public class DeductibleItemInventoryMap {
|
||||||
|
[XmlElement(ElementName = "UID", IsNullable = false)]
|
||||||
|
public int UserInventoryID { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "IID", IsNullable = false)]
|
||||||
|
public int ItemID { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "QTY", IsNullable = false)]
|
||||||
|
public int Quantity { get; set; }
|
||||||
|
}
|
26
src/Schema/FuseItemsRequest.cs
Normal file
26
src/Schema/FuseItemsRequest.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace sodoff.Schema;
|
||||||
|
|
||||||
|
[XmlRoot(ElementName = "FIR", Namespace = "")]
|
||||||
|
[Serializable]
|
||||||
|
public class FuseItemsRequest
|
||||||
|
{
|
||||||
|
[XmlElement(ElementName = "BPINVID", IsNullable = true)]
|
||||||
|
public int? BluePrintInventoryID { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "BPIID", IsNullable = true)]
|
||||||
|
public int? BluePrintItemID { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "DIIM", IsNullable = true)]
|
||||||
|
public List<DeductibleItemInventoryMap> DeductibleItemInventoryMaps { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "BPFIM", IsNullable = false)]
|
||||||
|
public List<BluePrintFuseItemMap> BluePrintFuseItemMaps { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "LOC", IsNullable = true)]
|
||||||
|
public string Locale { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "AGN", IsNullable = false)]
|
||||||
|
public Gender AvatarGender { get; set; }
|
||||||
|
}
|
20
src/Schema/FuseItemsResponse.cs
Normal file
20
src/Schema/FuseItemsResponse.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace sodoff.Schema;
|
||||||
|
|
||||||
|
[XmlRoot(ElementName = "FIRES", Namespace = "")]
|
||||||
|
[Serializable]
|
||||||
|
public class FuseItemsResponse
|
||||||
|
{
|
||||||
|
[XmlElement(ElementName = "ST", IsNullable = false)]
|
||||||
|
public Status Status { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "UID", IsNullable = false)]
|
||||||
|
public Guid UserID { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "IISM", IsNullable = true)]
|
||||||
|
public List<InventoryItemStatsMap> InventoryItemStatsMaps { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "VMSG", IsNullable = true)]
|
||||||
|
public ValidationMessage VMsg { get; set; }
|
||||||
|
}
|
16
src/Schema/InventoryItemStatsMap.cs
Normal file
16
src/Schema/InventoryItemStatsMap.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace sodoff.Schema;
|
||||||
|
|
||||||
|
[XmlRoot(ElementName = "IISM", Namespace = "")]
|
||||||
|
[Serializable]
|
||||||
|
public class InventoryItemStatsMap {
|
||||||
|
[XmlElement(ElementName = "CID", IsNullable = false)]
|
||||||
|
public int CommonInventoryID { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "ITM", IsNullable = false)]
|
||||||
|
public ItemData Item { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "ISM", IsNullable = false)]
|
||||||
|
public ItemStatsMap ItemStatsMap { get; set; }
|
||||||
|
}
|
16
src/Schema/LevelRewardType.cs
Normal file
16
src/Schema/LevelRewardType.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace sodoff.Schema;
|
||||||
|
|
||||||
|
[XmlRoot(ElementName = "GLRT")]
|
||||||
|
[Serializable]
|
||||||
|
public enum LevelRewardType {
|
||||||
|
[XmlEnum("1")]
|
||||||
|
LevelCompletion = 1,
|
||||||
|
|
||||||
|
[XmlEnum("2")]
|
||||||
|
LevelFailure = 2,
|
||||||
|
|
||||||
|
[XmlEnum("3")]
|
||||||
|
ExtraChest = 3
|
||||||
|
}
|
14
src/Schema/RaisedPetEntityMap.cs
Normal file
14
src/Schema/RaisedPetEntityMap.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace sodoff.Schema;
|
||||||
|
|
||||||
|
[XmlRoot(ElementName = "RPEM", Namespace = "")]
|
||||||
|
[Serializable]
|
||||||
|
public class RaisedPetEntityMap
|
||||||
|
{
|
||||||
|
[XmlElement(ElementName = "RPID")]
|
||||||
|
public int RaisedPetID { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "EID")]
|
||||||
|
public Guid? EntityID { get; set; }
|
||||||
|
}
|
20
src/Schema/RollUserItemRequest.cs
Normal file
20
src/Schema/RollUserItemRequest.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace sodoff.Schema;
|
||||||
|
|
||||||
|
[XmlRoot(ElementName = "RUIR", Namespace = "")]
|
||||||
|
[Serializable]
|
||||||
|
public class RollUserItemRequest
|
||||||
|
{
|
||||||
|
[XmlElement(ElementName = "CID", IsNullable = false)]
|
||||||
|
public int ContainerID { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "UIID", IsNullable = false)]
|
||||||
|
public int UserInventoryID { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "ISN", IsNullable = true)]
|
||||||
|
public string[] ItemStatNames { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "CIR", IsNullable = false)]
|
||||||
|
public CommonInventoryRequest[] InventoryItems { get; set; }
|
||||||
|
}
|
14
src/Schema/RollUserItemResponse.cs
Normal file
14
src/Schema/RollUserItemResponse.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace sodoff.Schema;
|
||||||
|
|
||||||
|
[XmlRoot(ElementName = "RUIRES", Namespace = "")]
|
||||||
|
[Serializable]
|
||||||
|
public class RollUserItemResponse
|
||||||
|
{
|
||||||
|
[XmlElement(ElementName = "ST", IsNullable = false)]
|
||||||
|
public Status Status { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "IS", IsNullable = false)]
|
||||||
|
public ItemStat[] ItemStats { get; set; }
|
||||||
|
}
|
14
src/Schema/SellItemsRequest.cs
Normal file
14
src/Schema/SellItemsRequest.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace sodoff.Schema;
|
||||||
|
|
||||||
|
[XmlRoot(ElementName = "SIR", Namespace = "")]
|
||||||
|
[Serializable]
|
||||||
|
public class SellItemsRequest
|
||||||
|
{
|
||||||
|
[XmlElement(ElementName = "CID", IsNullable = false)]
|
||||||
|
public int ContainerID { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "UICDS", IsNullable = false)]
|
||||||
|
public int[] UserInventoryCommonIDs { get; set; }
|
||||||
|
}
|
73
src/Schema/Status.cs
Normal file
73
src/Schema/Status.cs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace sodoff.Schema;
|
||||||
|
|
||||||
|
[XmlRoot(ElementName = "ST")]
|
||||||
|
[Serializable]
|
||||||
|
public enum Status {
|
||||||
|
[XmlEnum("1")]
|
||||||
|
Success = 1,
|
||||||
|
|
||||||
|
[XmlEnum("2")]
|
||||||
|
Failure,
|
||||||
|
|
||||||
|
[XmlEnum("3")]
|
||||||
|
ItemNotFound,
|
||||||
|
|
||||||
|
[XmlEnum("4")]
|
||||||
|
PoolItemsNotFound,
|
||||||
|
|
||||||
|
[XmlEnum("5")]
|
||||||
|
InvalidItemMap,
|
||||||
|
|
||||||
|
[XmlEnum("6")]
|
||||||
|
ItemNotFiltered,
|
||||||
|
|
||||||
|
[XmlEnum("7")]
|
||||||
|
InvalidInput,
|
||||||
|
|
||||||
|
[XmlEnum("8")]
|
||||||
|
InvalidGameMetaData,
|
||||||
|
|
||||||
|
[XmlEnum("9")]
|
||||||
|
InvalidItemRarity,
|
||||||
|
|
||||||
|
[XmlEnum("10")]
|
||||||
|
ItemStatsPersistFailed,
|
||||||
|
|
||||||
|
[XmlEnum("11")]
|
||||||
|
InvalidItemPayout,
|
||||||
|
|
||||||
|
[XmlEnum("12")]
|
||||||
|
InvalidStatsMap,
|
||||||
|
|
||||||
|
[XmlEnum("13")]
|
||||||
|
InvalidPossibleStatsMap,
|
||||||
|
|
||||||
|
[XmlEnum("14")]
|
||||||
|
ItemStatsNotExist,
|
||||||
|
|
||||||
|
[XmlEnum("15")]
|
||||||
|
ItemsNotMapped,
|
||||||
|
|
||||||
|
[XmlEnum("16")]
|
||||||
|
EventDataNotFound,
|
||||||
|
|
||||||
|
[XmlEnum("17")]
|
||||||
|
MissionDataNotFound,
|
||||||
|
|
||||||
|
[XmlEnum("18")]
|
||||||
|
SeasonRewardsNotFound,
|
||||||
|
|
||||||
|
[XmlEnum("19")]
|
||||||
|
ItemNotFoundInInventory,
|
||||||
|
|
||||||
|
[XmlEnum("20")]
|
||||||
|
BluePrintItemNotFound,
|
||||||
|
|
||||||
|
[XmlEnum("21")]
|
||||||
|
LowDeductibleItemQuantity,
|
||||||
|
|
||||||
|
[XmlEnum("22")]
|
||||||
|
InvalidBlueprintIngredients
|
||||||
|
}
|
25
src/Schema/UserItemStatsMap.cs
Normal file
25
src/Schema/UserItemStatsMap.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace sodoff.Schema;
|
||||||
|
|
||||||
|
[XmlRoot(ElementName = "UISM", Namespace = "")]
|
||||||
|
[Serializable]
|
||||||
|
public class UserItemStatsMap {
|
||||||
|
[XmlElement(ElementName = "UISMID", IsNullable = false)]
|
||||||
|
public int UserItemStatsMapID { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "UID")]
|
||||||
|
public Guid UserID { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "ITM", IsNullable = false)]
|
||||||
|
public ItemData Item { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "ISS", IsNullable = false)]
|
||||||
|
public ItemStat[] ItemStats { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "IT", IsNullable = true)]
|
||||||
|
public ItemTier? ItemTier { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "CD", IsNullable = true)]
|
||||||
|
public DateTime? CreatedDate { get; set; }
|
||||||
|
}
|
14
src/Schema/ValidationMessage.cs
Normal file
14
src/Schema/ValidationMessage.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace sodoff.Schema;
|
||||||
|
|
||||||
|
[XmlRoot(ElementName = "VMSG", Namespace = "")]
|
||||||
|
[Serializable]
|
||||||
|
public class ValidationMessage
|
||||||
|
{
|
||||||
|
[XmlElement(ElementName = "ST", IsNullable = false)]
|
||||||
|
public Status Status { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "EM", IsNullable = false)]
|
||||||
|
public string Message { get; set; }
|
||||||
|
}
|
@ -7,6 +7,7 @@ using System.Xml.Linq;
|
|||||||
|
|
||||||
namespace sodoff.Services {
|
namespace sodoff.Services {
|
||||||
public class AchievementService {
|
public class AchievementService {
|
||||||
|
private InventoryService inventoryService;
|
||||||
|
|
||||||
Dictionary<AchievementPointTypes, UserRank[]> ranks = new();
|
Dictionary<AchievementPointTypes, UserRank[]> ranks = new();
|
||||||
Dictionary<int, AchievementReward[]> achivmentsRewardByID = new();
|
Dictionary<int, AchievementReward[]> achivmentsRewardByID = new();
|
||||||
@ -15,7 +16,9 @@ namespace sodoff.Services {
|
|||||||
int dragonAdultMinXP;
|
int dragonAdultMinXP;
|
||||||
int dragonTitanMinXP;
|
int dragonTitanMinXP;
|
||||||
|
|
||||||
public AchievementService() {
|
public AchievementService(InventoryService inventoryService) {
|
||||||
|
this.inventoryService = inventoryService;
|
||||||
|
|
||||||
ArrayOfUserRank allranks = XmlUtil.DeserializeXml<ArrayOfUserRank>(XmlUtil.ReadResourceXmlString("allranks"));
|
ArrayOfUserRank allranks = XmlUtil.DeserializeXml<ArrayOfUserRank>(XmlUtil.ReadResourceXmlString("allranks"));
|
||||||
foreach (var pointType in Enum.GetValues<AchievementPointTypes>()) {
|
foreach (var pointType in Enum.GetValues<AchievementPointTypes>()) {
|
||||||
ranks[pointType] = allranks.UserRank.Where(r => r.PointTypeID == pointType).ToArray();
|
ranks[pointType] = allranks.UserRank.Where(r => r.PointTypeID == pointType).ToArray();
|
||||||
@ -100,24 +103,28 @@ namespace sodoff.Services {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AchievementReward AddAchievementPointsAndGetReward(Viking viking, AchievementPointTypes type, int value) {
|
||||||
|
AddAchievementPoints(viking, type, value);
|
||||||
|
return new AchievementReward{
|
||||||
|
EntityID = Guid.Parse(viking.Id),
|
||||||
|
PointTypeID = type,
|
||||||
|
EntityTypeID = 1, // player ?
|
||||||
|
RewardID = 1265, // TODO: placeholder
|
||||||
|
Amount = value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public void ApplyAchievementReward(Viking viking, AchievementReward reward) {
|
public void ApplyAchievementReward(Viking viking, AchievementReward reward) {
|
||||||
if (reward.PointTypeID == AchievementPointTypes.ItemReward) {
|
if (reward.PointTypeID == AchievementPointTypes.ItemReward) {
|
||||||
// TODO: This is not a pretty solution. Use inventory service in the future
|
inventoryService.AddItemToInventory(viking, reward.ItemID, (int)reward.Amount!);
|
||||||
InventoryItem? ii = viking.Inventory.InventoryItems.FirstOrDefault(x => x.ItemId == reward.ItemID);
|
|
||||||
if (ii is null) {
|
|
||||||
ii = new InventoryItem {
|
|
||||||
ItemId = reward.ItemID,
|
|
||||||
Quantity = 0
|
|
||||||
};
|
|
||||||
viking.Inventory.InventoryItems.Add(ii);
|
|
||||||
}
|
|
||||||
ii.Quantity += (int)reward.Amount!;
|
|
||||||
} else { // currencies, all types of player XP and dragon XP
|
} else { // currencies, all types of player XP and dragon XP
|
||||||
AddAchievementPoints(viking, reward.PointTypeID, reward.Amount);
|
AddAchievementPoints(viking, reward.PointTypeID, reward.Amount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public AchievementReward[] ApplyAchievementRewards(Viking viking, AchievementReward[] rewards) {
|
public AchievementReward[] ApplyAchievementRewards(Viking viking, AchievementReward[] rewards) {
|
||||||
|
if (rewards is null)
|
||||||
|
return null;
|
||||||
foreach (var reward in rewards) {
|
foreach (var reward in rewards) {
|
||||||
ApplyAchievementReward(viking, reward);
|
ApplyAchievementReward(viking, reward);
|
||||||
/* TODO we don't need this?
|
/* TODO we don't need this?
|
||||||
|
115
src/Services/InventoryService.cs
Normal file
115
src/Services/InventoryService.cs
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
using sodoff.Model;
|
||||||
|
using sodoff.Schema;
|
||||||
|
using sodoff.Util;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace sodoff.Services {
|
||||||
|
public class InventoryService {
|
||||||
|
|
||||||
|
private readonly DBContext ctx;
|
||||||
|
private ItemService itemService;
|
||||||
|
|
||||||
|
public const int Shards = 13711;
|
||||||
|
|
||||||
|
public InventoryService(DBContext ctx, ItemService itemService) {
|
||||||
|
this.ctx = ctx;
|
||||||
|
this.itemService = itemService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InventoryItem AddItemToInventory(Viking viking, int itemID, int quantity) {
|
||||||
|
InventoryItem? item = null;
|
||||||
|
if (!ItemNeedUniqueInventorySlot(itemID))
|
||||||
|
item = viking.Inventory.InventoryItems.FirstOrDefault(e => e.ItemId == itemID);
|
||||||
|
if (item is null) {
|
||||||
|
item = new InventoryItem {
|
||||||
|
ItemId = itemID,
|
||||||
|
Quantity = 0
|
||||||
|
};
|
||||||
|
viking.Inventory.InventoryItems.Add(item);
|
||||||
|
}
|
||||||
|
item.Quantity += quantity;
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommonInventoryResponseItem AddItemToInventoryAndGetResponse(Viking viking, int itemID, int quantity) {
|
||||||
|
InventoryItem item = AddItemToInventory(viking, itemID, quantity);
|
||||||
|
|
||||||
|
ctx.SaveChanges(); // We need to get the ID of the newly created item
|
||||||
|
|
||||||
|
if (quantity == 1)
|
||||||
|
quantity = 0; // The game expects 0 if quantity got updated by just 1
|
||||||
|
// Otherwise it expects the quantity from the request
|
||||||
|
return new CommonInventoryResponseItem {
|
||||||
|
CommonInventoryID = item.Id,
|
||||||
|
ItemID = itemID,
|
||||||
|
Quantity = quantity
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public InventoryItemStatsMap AddBattleItemToInventory(Viking viking, int itemId, int itemTier, ItemStat[] itemStat = null) {
|
||||||
|
// get item data
|
||||||
|
ItemData itemData = itemService.GetItem(itemId);
|
||||||
|
|
||||||
|
// create new item
|
||||||
|
InventoryItem item = new InventoryItem { ItemId = itemId, Quantity = 1 };
|
||||||
|
ItemStatsMap itemStatsMap = new ItemStatsMap {
|
||||||
|
ItemID = itemId,
|
||||||
|
ItemTier = (ItemTier)itemTier,
|
||||||
|
ItemStats = itemStat ?? itemService.CreateItemStats(itemData.PossibleStatsMap, (int)itemData.ItemRarity, itemTier).ToArray()
|
||||||
|
};
|
||||||
|
item.StatsSerialized = XmlUtil.SerializeXml(itemStatsMap);
|
||||||
|
|
||||||
|
// add to viking
|
||||||
|
viking.Inventory.InventoryItems.Add(item);
|
||||||
|
ctx.SaveChanges(); // We need to get the ID of the newly created item
|
||||||
|
|
||||||
|
// return item with stats
|
||||||
|
return new InventoryItemStatsMap {
|
||||||
|
CommonInventoryID = item.Id,
|
||||||
|
Item = itemData,
|
||||||
|
ItemStatsMap = itemStatsMap
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommonInventoryData GetCommonInventoryData(Viking viking) {
|
||||||
|
List<InventoryItem> items = viking.Inventory.InventoryItems.ToList();
|
||||||
|
|
||||||
|
List<UserItemData> userItemData = new();
|
||||||
|
foreach (InventoryItem item in items) {
|
||||||
|
if (item.Quantity == 0) continue; // Don't include an item that the viking doesn't have
|
||||||
|
ItemData itemData = itemService.GetItem(item.ItemId);
|
||||||
|
UserItemData uid = new UserItemData {
|
||||||
|
UserInventoryID = item.Id,
|
||||||
|
ItemID = itemData.ItemID,
|
||||||
|
Quantity = item.Quantity,
|
||||||
|
Uses = itemData.Uses,
|
||||||
|
ModifiedDate = new DateTime(DateTime.Now.Ticks),
|
||||||
|
Item = itemData
|
||||||
|
};
|
||||||
|
if (item.StatsSerialized != null) {
|
||||||
|
ItemStatsMap itemStats = XmlUtil.DeserializeXml<ItemStatsMap>(item.StatsSerialized);
|
||||||
|
uid.ItemStats = itemStats.ItemStats;
|
||||||
|
uid.ItemTier = itemStats.ItemTier;
|
||||||
|
} else if (itemData.ItemStatsMap != null) {
|
||||||
|
uid.ItemStats = itemData.ItemStatsMap?.ItemStats;
|
||||||
|
uid.ItemTier = itemData.ItemStatsMap?.ItemTier;
|
||||||
|
}
|
||||||
|
userItemData.Add(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CommonInventoryData {
|
||||||
|
UserID = Guid.Parse(viking.Id),
|
||||||
|
Item = userItemData.ToArray()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ItemNeedUniqueInventorySlot(int itemId) {
|
||||||
|
return itemService.ItemHasCategory(
|
||||||
|
itemService.GetItem(itemId), new int[] {
|
||||||
|
541, // farm expansion
|
||||||
|
511, // dragons tactics (battle) items
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,16 +8,86 @@ namespace sodoff.Services {
|
|||||||
public class ItemService {
|
public class ItemService {
|
||||||
|
|
||||||
Dictionary<int, ItemData> items = new();
|
Dictionary<int, ItemData> items = new();
|
||||||
|
int[] itemsRewardForDT;
|
||||||
|
Random random = new Random();
|
||||||
|
|
||||||
public ItemService() {
|
public ItemService() {
|
||||||
ServerItemArray itemArray = XmlUtil.DeserializeXml<ServerItemArray>(XmlUtil.ReadResourceXmlString("items"));
|
ServerItemArray itemArray = XmlUtil.DeserializeXml<ServerItemArray>(XmlUtil.ReadResourceXmlString("items"));
|
||||||
foreach (var item in itemArray.ItemDataArray) {
|
foreach (var item in itemArray.ItemDataArray) {
|
||||||
items.Add(item.ItemID, item);
|
items.Add(item.ItemID, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
itemsRewardForDT = XmlUtil.DeserializeXml<int[]>(XmlUtil.ReadResourceXmlString("dtrewards"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ItemData GetItem(int id) {
|
public ItemData GetItem(int id) {
|
||||||
return items[id];
|
return items[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ItemData GetDTReward() {
|
||||||
|
// TODO: better calculation of reward item - use difficulty of DT level, item rarity, tier, etc
|
||||||
|
int itemID = itemsRewardForDT[random.Next(0, itemsRewardForDT.Length)];
|
||||||
|
return items[itemID];
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemDataRelationship OpenBox(ItemData boxItem) {
|
||||||
|
var boxRewards = boxItem.Relationship.Where(e => e.Type == "Prize").ToArray();
|
||||||
|
int totalWeight = boxRewards.Sum(e => e.Weight);
|
||||||
|
if (totalWeight == 0) {
|
||||||
|
return boxRewards[random.Next(0, boxRewards.Length)];
|
||||||
|
}
|
||||||
|
int cnt = 0;
|
||||||
|
int win = random.Next(0, totalWeight);
|
||||||
|
foreach (var reward in boxRewards) {
|
||||||
|
cnt += reward.Weight;
|
||||||
|
if (cnt > win) {
|
||||||
|
return reward;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ItemHasCategory(ItemData itemData, int categoryId) {
|
||||||
|
ItemDataCategory? category = itemData.Category?.FirstOrDefault(e => e.CategoryId == categoryId);
|
||||||
|
return category != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ItemHasCategory(ItemData itemData, int[] categoryIds) {
|
||||||
|
ItemDataCategory? category = itemData.Category?.FirstOrDefault(e => categoryIds.Contains(e.CategoryId));
|
||||||
|
return category != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ItemStat> CreateItemStats(ItemPossibleStatsMap? possibleStats, int rarity, int itemTier) {
|
||||||
|
List<ItemStat> newStat = new List<ItemStat>();
|
||||||
|
int rMax = possibleStats.Stats.Sum(e => e.Probability);
|
||||||
|
for (int i=0; i<rarity && rMax > 0; ++i) {
|
||||||
|
int val = random.Next(0, rMax);
|
||||||
|
int cnt = 0;
|
||||||
|
foreach (var stat in possibleStats.Stats) {
|
||||||
|
if (newStat.FirstOrDefault(e => e.ItemStatID == stat.ItemStatsID) != null) {
|
||||||
|
// this type of stat already is in newStat ... is excluded from this draw
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
cnt += stat.Probability;
|
||||||
|
if (cnt > val) {
|
||||||
|
rMax -= stat.Probability; // do not include in the next draw
|
||||||
|
|
||||||
|
StatRangeMap rangeMap = stat.ItemStatsRangeMaps.FirstOrDefault(e => e.ItemTierID == itemTier);
|
||||||
|
newStat.Add(
|
||||||
|
new ItemStat {
|
||||||
|
ItemStatID = rangeMap.ItemStatsID,
|
||||||
|
Name = rangeMap.ItemStatsName,
|
||||||
|
Value = random.Next(rangeMap.StartRange, rangeMap.EndRange+1).ToString(),
|
||||||
|
DataType = DataTypeInfo.Int
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
break; // we found new stat for slot "i" ... goto i+1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newStat;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,9 @@
|
|||||||
<None Update="Resources\achievementstasks.xml">
|
<None Update="Resources\achievementstasks.xml">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
|
<None Update="Resources\dtrewards.xml">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="Resources\rewardmultiplier.xml">
|
<EmbeddedResource Include="Resources\rewardmultiplier.xml">
|
||||||
@ -66,6 +69,9 @@
|
|||||||
<EmbeddedResource Include="Resources\achievementstasks.xml">
|
<EmbeddedResource Include="Resources\achievementstasks.xml">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="Resources\dtrewards.xml">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</EmbeddedResource>
|
||||||
<EmbeddedResource Include="Resources\items.xml">
|
<EmbeddedResource Include="Resources\items.xml">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user