mirror of
https://github.com/SoDOff-Project/sodoff.git
synced 2025-10-11 08:18:49 -07:00
support AchievementTask and AchievementID rewards (#25)
- add task and id reward xml databases - thanks to Project Edge community for sniffed network data! - implement SetAchievementAndGetReward, SetUserAchievementAndGetReward - partially implement SetUserAchievementTask - move rewards logic to AchievementService - show real value of farming and fishing XP - show UDP points Co-authored-by: Spirtix <michal.prazak1@gmail.com>
This commit is contained in:
parent
dd9dfa4873
commit
665089d5ef
@ -76,6 +76,9 @@ Then run School of Dragons.
|
||||
- UseInventory
|
||||
- DeleteProfile
|
||||
- DeleteAccountNotification
|
||||
- SetAchievementAndGetReward
|
||||
- GetAchievementsByUserID
|
||||
- GetPetAchievementsByUserID
|
||||
|
||||
#### Implemented enough (probably)
|
||||
- GetRules (doesn't return any rules, probably doesn't need to)
|
||||
@ -85,6 +88,7 @@ Then run School of Dragons.
|
||||
- GetCommonInventory
|
||||
- GetUserRoomItemPositions
|
||||
- SetUserRoomItemPositions
|
||||
- SetUserAchievementAndGetReward (works like SetAchievementAndGetReward)
|
||||
|
||||
#### Partially implemented
|
||||
- GetUserProfileByUserID (a lot is still placeholder)
|
||||
@ -96,10 +100,10 @@ Then run School of Dragons.
|
||||
- GetUserRoomList (room categories are not implemented)
|
||||
- SetNextItemState (may require more work, we don't know yet)
|
||||
- SetUserRoom
|
||||
- SetUserAchievementTask (returns a real reward but still use task placeholder)
|
||||
|
||||
#### Currently static or stubbed
|
||||
- GetAllRanks (needs to be populated with what ranks the user has)
|
||||
- GetPetAchievementsByUserId (always returns null)
|
||||
- GetAchievementTaskInfo (returns a static XML)
|
||||
- GetAllRewardTypeMultiplier (returns a static XML)
|
||||
- GetBuddyList (returns an emtpy array)
|
||||
@ -109,9 +113,6 @@ Then run School of Dragons.
|
||||
- SaveMessage (doesn't do anything and returns false)
|
||||
- GetMMOServerInfoWithZone (returns an empty array)
|
||||
- GetActiveChallenges (returns an empty array)
|
||||
- GetAchievementsByUserID (returns an achievement with the provided user ID)
|
||||
- SetAchievementAndGetReward (returns 5 gems)
|
||||
- SetUserAchievementTask (returns a placeholder achievement)
|
||||
- GetAnnouncementsByUser (returns no announcements, but that might be sufficient)
|
||||
- GetAverageRatingForRoom (return max rating)
|
||||
- GetUserActivityByUserID (returns an empty array)
|
||||
|
@ -115,8 +115,9 @@ public class AchievementController : Controller {
|
||||
return Ok(new ArrayOfUserAchievementInfo {
|
||||
UserAchievementInfo = new UserAchievementInfo[]{
|
||||
achievementService.CreateUserAchievementInfo(viking, AchievementPointTypes.PlayerXP),
|
||||
achievementService.CreateUserAchievementInfo(viking.Id, 60000, AchievementPointTypes.PlayerFarmingXP), // TODO: placeholder until there is no leveling for farm XP
|
||||
achievementService.CreateUserAchievementInfo(viking.Id, 20000, AchievementPointTypes.PlayerFishingXP), // TODO: placeholder until there is no leveling for fishing XP
|
||||
achievementService.CreateUserAchievementInfo(viking, AchievementPointTypes.PlayerFarmingXP),
|
||||
achievementService.CreateUserAchievementInfo(viking, AchievementPointTypes.PlayerFishingXP),
|
||||
achievementService.CreateUserAchievementInfo(viking, AchievementPointTypes.UDTPoints),
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -136,45 +137,51 @@ public class AchievementController : Controller {
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("AchievementWebService.asmx/SetAchievementAndGetReward")]
|
||||
[Route("AchievementWebService.asmx/SetUserAchievementAndGetReward")]
|
||||
public IActionResult SetAchievementAndGetReward([FromForm] string apiToken, [FromForm] int achievementID) {
|
||||
// TODO: This is a placeholder; returns 5 gems
|
||||
Viking? viking = ctx.Sessions.FirstOrDefault(x => x.ApiToken == apiToken).Viking;
|
||||
return Ok(new AchievementReward[1] {
|
||||
new AchievementReward {
|
||||
Amount = 5,
|
||||
PointTypeID = AchievementPointTypes.CashCurrency,
|
||||
EntityID = Guid.Parse(viking.Id),
|
||||
EntityTypeID = 1,
|
||||
RewardID = 552
|
||||
}
|
||||
});
|
||||
|
||||
if (viking is null) {
|
||||
return Unauthorized();
|
||||
}
|
||||
|
||||
var rewards = achievementService.ApplyAchievementRewardsByID(viking, achievementID);
|
||||
ctx.SaveChanges();
|
||||
|
||||
return Ok(rewards);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Produces("application/xml")]
|
||||
[Route("V2/AchievementWebService.asmx/SetUserAchievementTask")]
|
||||
[DecryptRequest("achievementTaskSetRequest")]
|
||||
public IActionResult SetUserAchievementTask([FromForm] string apiToken, [FromForm] int achievementID) {
|
||||
// TODO: This is a placeholder
|
||||
string xml = Request.Form["achievementTaskSetRequest"];
|
||||
AchievementTaskSetResponse response = new AchievementTaskSetResponse {
|
||||
Success = true,
|
||||
UserMessage = true,
|
||||
AchievementName = "Placeholder Achievement",
|
||||
Level = 1,
|
||||
AchievementTaskGroupID = 1279,
|
||||
LastLevelCompleted = true,
|
||||
AchievementInfoID = 1279,
|
||||
AchievementRewards = new AchievementReward[1] {
|
||||
new AchievementReward {
|
||||
Amount = 25,
|
||||
PointTypeID = AchievementPointTypes.PlayerXP,
|
||||
RewardID = 910,
|
||||
EntityTypeID =1
|
||||
public IActionResult SetUserAchievementTask([FromForm] string apiToken) {
|
||||
Viking? viking = ctx.Sessions.FirstOrDefault(x => x.ApiToken == apiToken).Viking;
|
||||
|
||||
if (viking is null) {
|
||||
return Unauthorized();
|
||||
}
|
||||
|
||||
AchievementTaskSetRequest request = XmlUtil.DeserializeXml<AchievementTaskSetRequest>(Request.Form["achievementTaskSetRequest"]);
|
||||
|
||||
var response = new List<AchievementTaskSetResponse>();
|
||||
foreach (var task in request.AchievementTaskSet) {
|
||||
response.Add(
|
||||
new AchievementTaskSetResponse {
|
||||
Success = true,
|
||||
UserMessage = true, // TODO: placeholder
|
||||
AchievementName = "Placeholder Achievement", // TODO: placeholder
|
||||
Level = 1, // TODO: placeholder
|
||||
AchievementTaskGroupID = 1279, // TODO: placeholder
|
||||
LastLevelCompleted = true, // TODO: placeholder
|
||||
AchievementInfoID = 1279, // TODO: placeholder
|
||||
AchievementRewards = achievementService.ApplyAchievementRewardsByTask(viking, task)
|
||||
}
|
||||
}
|
||||
};
|
||||
return Ok(new ArrayOfAchievementTaskSetResponse { AchievementTaskSetResponse = new AchievementTaskSetResponse[1] { response } });
|
||||
);
|
||||
}
|
||||
ctx.SaveChanges();
|
||||
|
||||
return Ok(new ArrayOfAchievementTaskSetResponse { AchievementTaskSetResponse = response.ToArray() });
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
|
@ -145,8 +145,9 @@ public class ProfileController : Controller {
|
||||
AchievementInfo = null, // placeholder
|
||||
Achievements = new UserAchievementInfo[] {
|
||||
achievementService.CreateUserAchievementInfo(viking, AchievementPointTypes.PlayerXP),
|
||||
achievementService.CreateUserAchievementInfo(viking.Id, 60000, AchievementPointTypes.PlayerFarmingXP), // TODO: placeholder until there is no leveling for farm XP
|
||||
achievementService.CreateUserAchievementInfo(viking.Id, 20000, AchievementPointTypes.PlayerFishingXP), // TODO: placeholder until there is no leveling for fishing XP
|
||||
achievementService.CreateUserAchievementInfo(viking, AchievementPointTypes.PlayerFarmingXP),
|
||||
achievementService.CreateUserAchievementInfo(viking, AchievementPointTypes.PlayerFishingXP),
|
||||
achievementService.CreateUserAchievementInfo(viking, AchievementPointTypes.UDTPoints),
|
||||
}
|
||||
};
|
||||
|
||||
|
1536
src/Resources/achievementsids.xml
Normal file
1536
src/Resources/achievementsids.xml
Normal file
File diff suppressed because it is too large
Load Diff
1032
src/Resources/achievementstasks.xml
Normal file
1032
src/Resources/achievementstasks.xml
Normal file
File diff suppressed because it is too large
Load Diff
@ -32,4 +32,7 @@ public enum AchievementPointTypes {
|
||||
|
||||
[XmlEnum("13")]
|
||||
Unknown13 = 13,
|
||||
|
||||
[XmlEnum("21")]
|
||||
Unknown21 = 21,
|
||||
}
|
||||
|
26
src/Schema/AchievementTask.cs
Normal file
26
src/Schema/AchievementTask.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace sodoff.Schema;
|
||||
|
||||
[XmlRoot(ElementName = "ATS", Namespace = "")]
|
||||
[Serializable]
|
||||
public class AchievementTask
|
||||
{
|
||||
[XmlElement(ElementName = "oid")]
|
||||
public string OwnerID;
|
||||
|
||||
[XmlElement(ElementName = "tid")]
|
||||
public int TaskID;
|
||||
|
||||
[XmlElement(ElementName = "aiid")]
|
||||
public int AchievementInfoID;
|
||||
|
||||
[XmlElement(ElementName = "rid")]
|
||||
public string RelatedID;
|
||||
|
||||
[XmlElement(ElementName = "pts")]
|
||||
public int Points;
|
||||
|
||||
[XmlElement(ElementName = "etid")]
|
||||
public int EntityTypeID;
|
||||
}
|
11
src/Schema/AchievementTaskSetRequest.cs
Normal file
11
src/Schema/AchievementTaskSetRequest.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace sodoff.Schema;
|
||||
|
||||
[XmlRoot(ElementName = "ATSRQ", Namespace = "")]
|
||||
[Serializable]
|
||||
public class AchievementTaskSetRequest
|
||||
{
|
||||
[XmlElement(ElementName = "as")]
|
||||
public AchievementTask[] AchievementTaskSet { get; set; }
|
||||
}
|
14
src/Schema/AchievementsIdInfo.cs
Normal file
14
src/Schema/AchievementsIdInfo.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace sodoff.Schema;
|
||||
|
||||
[XmlRoot(ElementName = "AchievementsIdInfo", Namespace = "")]
|
||||
[Serializable]
|
||||
public class AchievementsIdInfo
|
||||
{
|
||||
[XmlElement(ElementName = "AID")]
|
||||
public int AchievementID;
|
||||
|
||||
[XmlElement(ElementName = "AR")]
|
||||
public AchievementReward[] AchievementReward;
|
||||
}
|
14
src/Schema/AchievementsTaskInfo.cs
Normal file
14
src/Schema/AchievementsTaskInfo.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace sodoff.Schema;
|
||||
|
||||
[XmlRoot(ElementName = "AchievementsTaskInfo", Namespace = "")]
|
||||
[Serializable]
|
||||
public class AchievementsTaskInfo
|
||||
{
|
||||
[XmlElement(ElementName = "TID")]
|
||||
public int TaskID;
|
||||
|
||||
[XmlElement(ElementName = "AR")]
|
||||
public AchievementReward[] AchievementReward;
|
||||
}
|
@ -9,17 +9,28 @@ namespace sodoff.Services {
|
||||
public class AchievementService {
|
||||
|
||||
Dictionary<AchievementPointTypes, UserRank[]> ranks = new();
|
||||
Dictionary<int, AchievementReward[]> achivmentsRewardByID = new();
|
||||
Dictionary<int, AchievementReward[]> achivmentsRewardByTask = new();
|
||||
|
||||
int dragonAdultMinXP;
|
||||
int dragonTitanMinXP;
|
||||
|
||||
public AchievementService() {
|
||||
ArrayOfUserRank allranks = XmlUtil.DeserializeXml<ArrayOfUserRank>(XmlUtil.ReadResourceXmlString("allranks"));
|
||||
|
||||
foreach (var pointType in Enum.GetValues<AchievementPointTypes>()) {
|
||||
ranks[pointType] = allranks.UserRank.Where(r => r.PointTypeID == pointType).ToArray();
|
||||
}
|
||||
|
||||
AchievementsIdInfo[] allAchievementsIdInfo = XmlUtil.DeserializeXml<AchievementsIdInfo[]>(XmlUtil.ReadResourceXmlString("achievementsids"));
|
||||
foreach (var achievementsIdInfo in allAchievementsIdInfo) {
|
||||
achivmentsRewardByID[achievementsIdInfo.AchievementID] = achievementsIdInfo.AchievementReward;
|
||||
}
|
||||
|
||||
AchievementsTaskInfo[] allAchievementsTaskInfo = XmlUtil.DeserializeXml<AchievementsTaskInfo[]>(XmlUtil.ReadResourceXmlString("achievementstasks"));
|
||||
foreach (var achievementsTaskInfo in allAchievementsTaskInfo) {
|
||||
achivmentsRewardByTask[achievementsTaskInfo.TaskID] = achievementsTaskInfo.AchievementReward;
|
||||
}
|
||||
|
||||
dragonAdultMinXP = ranks[AchievementPointTypes.DragonXP][10].Value;
|
||||
dragonTitanMinXP = ranks[AchievementPointTypes.DragonXP][20].Value;
|
||||
}
|
||||
@ -88,5 +99,56 @@ namespace sodoff.Services {
|
||||
xpPoints.Value += value ?? 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyAchievementReward(Viking viking, AchievementReward reward) {
|
||||
if (reward.PointTypeID == AchievementPointTypes.ItemReward) {
|
||||
// TODO: This is not a pretty solution. Use inventory service in the future
|
||||
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
|
||||
AddAchievementPoints(viking, reward.PointTypeID, reward.Amount);
|
||||
}
|
||||
}
|
||||
|
||||
public AchievementReward[] ApplyAchievementRewards(Viking viking, AchievementReward[] rewards) {
|
||||
foreach (var reward in rewards) {
|
||||
ApplyAchievementReward(viking, reward);
|
||||
/* TODO we don't need this?
|
||||
if (reward.PointTypeID == AchievementPointTypes.DragonXP) {
|
||||
reward.EntityID = Guid.Parse(viking.SelectedDragon.EntityId)
|
||||
} else {
|
||||
reward.EntityID = Guid.Parse(viking.Id)
|
||||
} */
|
||||
}
|
||||
// TODO: check trophies, etc criteria and id need apply and add to results extra reward here
|
||||
return rewards;
|
||||
}
|
||||
|
||||
public AchievementReward[] ApplyAchievementRewardsByID(Viking viking, int achievementID) {
|
||||
if (achivmentsRewardByID.ContainsKey(achievementID)) {
|
||||
var rewards = achivmentsRewardByID[achievementID];
|
||||
return ApplyAchievementRewards(viking, rewards);
|
||||
} else {
|
||||
Console.WriteLine(string.Format("Unknown rewards for achievementID={0}", achievementID));
|
||||
return new AchievementReward[0];
|
||||
}
|
||||
}
|
||||
|
||||
public AchievementReward[] ApplyAchievementRewardsByTask(Viking viking, AchievementTask task) {
|
||||
if (achivmentsRewardByTask.ContainsKey(task.TaskID)) {
|
||||
var rewards = achivmentsRewardByTask[task.TaskID];
|
||||
return ApplyAchievementRewards(viking, rewards);
|
||||
} else {
|
||||
Console.WriteLine(string.Format("Unknown rewards for taskID={0}", task.TaskID));
|
||||
return new AchievementReward[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,11 +38,6 @@ public class MissionService {
|
||||
if (completed) {
|
||||
Mission mission = GetMissionWithProgress(missionId, userId);
|
||||
if (MissionCompleted(mission)) {
|
||||
// Get mission rewards
|
||||
result.Add(new MissionCompletedResult {
|
||||
MissionID = missionId,
|
||||
Rewards = mission.Rewards.ToArray()
|
||||
});
|
||||
// Update mission from active to completed
|
||||
Viking viking = ctx.Vikings.FirstOrDefault(x => x.Id == userId)!;
|
||||
MissionState? missionState = viking.MissionStates.FirstOrDefault(x => x.MissionId == missionId);
|
||||
@ -50,23 +45,14 @@ public class MissionService {
|
||||
missionState.MissionStatus = MissionStatus.Completed;
|
||||
missionState.UserAccepted = null;
|
||||
}
|
||||
foreach (var reward in mission.Rewards) {
|
||||
if (reward.PointTypeID == AchievementPointTypes.ItemReward) {
|
||||
// TODO: This is not a pretty solution. Use inventory service in the future
|
||||
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
|
||||
achievementService.AddAchievementPoints(viking, reward.PointTypeID, reward.Amount);
|
||||
}
|
||||
}
|
||||
var rewards = achievementService.ApplyAchievementRewards(viking, mission.Rewards.ToArray());
|
||||
ctx.SaveChanges();
|
||||
|
||||
// Get mission rewards
|
||||
result.Add(new MissionCompletedResult {
|
||||
MissionID = missionId,
|
||||
Rewards = rewards
|
||||
});
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -9,11 +9,14 @@ namespace sodoff.Services;
|
||||
public class RoomService {
|
||||
|
||||
private readonly DBContext ctx;
|
||||
private ItemService itemService;
|
||||
|
||||
public RoomService(DBContext ctx, ItemService itemService) {
|
||||
private ItemService itemService;
|
||||
private AchievementService achievementService;
|
||||
|
||||
public RoomService(DBContext ctx, ItemService itemService, AchievementService achievementService) {
|
||||
this.ctx = ctx;
|
||||
this.itemService = itemService;
|
||||
this.achievementService = achievementService;
|
||||
}
|
||||
|
||||
public void CreateRoom(Viking viking, string roomId) {
|
||||
@ -131,21 +134,7 @@ public class RoomService {
|
||||
}
|
||||
|
||||
if (rewards != null) {
|
||||
response.Rewards = rewards;
|
||||
foreach (var reward in rewards) {
|
||||
if (reward.PointTypeID == AchievementPointTypes.ItemReward) {
|
||||
// TODO: This is not a pretty solution. Use inventory service in the future
|
||||
InventoryItem? ii = item.Room.Viking.Inventory.InventoryItems.FirstOrDefault(x => x.ItemId == reward.ItemID);
|
||||
if (ii is null) {
|
||||
ii = new InventoryItem {
|
||||
ItemId = reward.ItemID,
|
||||
Quantity = 0
|
||||
};
|
||||
item.Room.Viking.Inventory.InventoryItems.Add(ii);
|
||||
}
|
||||
ii.Quantity += (int)reward.Amount!;
|
||||
}
|
||||
}
|
||||
response.Rewards = achievementService.ApplyAchievementRewards(item.Room.Viking, rewards);
|
||||
}
|
||||
|
||||
DateTime stateChange = new DateTime(DateTime.Now.Ticks);
|
||||
|
@ -20,6 +20,8 @@
|
||||
<None Remove="Resources\rewardmultiplier.xml" />
|
||||
<None Remove="Resources\store.xml" />
|
||||
<None Remove="Resources\allranks.xml" />
|
||||
<None Remove="Resources\achievementsids.xml" />
|
||||
<None Remove="Resources\achievementstasks.xml" />
|
||||
<None Remove="Resources\defaultmissionlist.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@ -35,6 +37,12 @@
|
||||
<None Update="Resources\tutorialmission.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Resources\achievementsids.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Resources\achievementstasks.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\rewardmultiplier.xml">
|
||||
@ -52,6 +60,12 @@
|
||||
<EmbeddedResource Include="Resources\allranks.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Resources\achievementsids.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Resources\achievementstasks.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Resources\items.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
|
Loading…
x
Reference in New Issue
Block a user