1316 lines
37 KiB
Go
1316 lines
37 KiB
Go
package quests
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// Test Location functionality
|
|
func TestNewLocation(t *testing.T) {
|
|
id := int32(1)
|
|
x, y, z := float32(10.5), float32(20.3), float32(30.7)
|
|
zoneID := int32(100)
|
|
|
|
loc := NewLocation(id, x, y, z, zoneID)
|
|
if loc == nil {
|
|
t.Fatal("NewLocation returned nil")
|
|
}
|
|
|
|
if loc.ID != id {
|
|
t.Errorf("Expected ID %d, got %d", id, loc.ID)
|
|
}
|
|
if loc.X != x {
|
|
t.Errorf("Expected X %f, got %f", x, loc.X)
|
|
}
|
|
if loc.Y != y {
|
|
t.Errorf("Expected Y %f, got %f", y, loc.Y)
|
|
}
|
|
if loc.Z != z {
|
|
t.Errorf("Expected Z %f, got %f", z, loc.Z)
|
|
}
|
|
if loc.ZoneID != zoneID {
|
|
t.Errorf("Expected ZoneID %d, got %d", zoneID, loc.ZoneID)
|
|
}
|
|
}
|
|
|
|
// Test QuestFactionPrereq functionality
|
|
func TestNewQuestFactionPrereq(t *testing.T) {
|
|
factionID := int32(123)
|
|
min, max := int32(-1000), int32(1000)
|
|
|
|
prereq := NewQuestFactionPrereq(factionID, min, max)
|
|
if prereq == nil {
|
|
t.Fatal("NewQuestFactionPrereq returned nil")
|
|
}
|
|
|
|
if prereq.FactionID != factionID {
|
|
t.Errorf("Expected FactionID %d, got %d", factionID, prereq.FactionID)
|
|
}
|
|
if prereq.Min != min {
|
|
t.Errorf("Expected Min %d, got %d", min, prereq.Min)
|
|
}
|
|
if prereq.Max != max {
|
|
t.Errorf("Expected Max %d, got %d", max, prereq.Max)
|
|
}
|
|
}
|
|
|
|
// Test QuestStep functionality
|
|
func TestNewQuestStep(t *testing.T) {
|
|
id := int32(1)
|
|
stepType := StepTypeKill
|
|
description := "Kill 5 goblins"
|
|
ids := []int32{100, 101, 102}
|
|
quantity := int32(5)
|
|
taskGroup := "Combat Tasks"
|
|
maxVariation := float32(10.0)
|
|
percentage := float32(90.0)
|
|
usableItemID := int32(0)
|
|
|
|
step := NewQuestStep(id, stepType, description, ids, quantity, taskGroup, nil, maxVariation, percentage, usableItemID)
|
|
if step == nil {
|
|
t.Fatal("NewQuestStep returned nil")
|
|
}
|
|
|
|
// Test basic properties
|
|
if step.ID != id {
|
|
t.Errorf("Expected ID %d, got %d", id, step.ID)
|
|
}
|
|
if step.Type != stepType {
|
|
t.Errorf("Expected Type %d, got %d", stepType, step.Type)
|
|
}
|
|
if step.Description != description {
|
|
t.Errorf("Expected Description '%s', got '%s'", description, step.Description)
|
|
}
|
|
if step.TaskGroup != taskGroup {
|
|
t.Errorf("Expected TaskGroup '%s', got '%s'", taskGroup, step.TaskGroup)
|
|
}
|
|
if step.Quantity != quantity {
|
|
t.Errorf("Expected Quantity %d, got %d", quantity, step.Quantity)
|
|
}
|
|
if step.MaxVariation != maxVariation {
|
|
t.Errorf("Expected MaxVariation %f, got %f", maxVariation, step.MaxVariation)
|
|
}
|
|
if step.Percentage != percentage {
|
|
t.Errorf("Expected Percentage %f, got %f", percentage, step.Percentage)
|
|
}
|
|
if step.UsableItemID != usableItemID {
|
|
t.Errorf("Expected UsableItemID %d, got %d", usableItemID, step.UsableItemID)
|
|
}
|
|
|
|
// Test IDs map
|
|
if len(step.IDs) != len(ids) {
|
|
t.Errorf("Expected %d IDs, got %d", len(ids), len(step.IDs))
|
|
}
|
|
for _, expectedID := range ids {
|
|
if !step.IDs[expectedID] {
|
|
t.Errorf("Expected ID %d to be in IDs map", expectedID)
|
|
}
|
|
}
|
|
|
|
// Test defaults
|
|
if step.StepProgress != 0 {
|
|
t.Errorf("Expected StepProgress 0, got %d", step.StepProgress)
|
|
}
|
|
if step.Icon != DefaultIcon {
|
|
t.Errorf("Expected Icon %d, got %d", DefaultIcon, step.Icon)
|
|
}
|
|
if step.Updated != false {
|
|
t.Errorf("Expected Updated false, got %t", step.Updated)
|
|
}
|
|
}
|
|
|
|
func TestQuestStepLocation(t *testing.T) {
|
|
id := int32(2)
|
|
stepType := StepTypeLocation
|
|
description := "Visit the ancient ruins"
|
|
locations := []*Location{
|
|
NewLocation(1, 100.0, 200.0, 300.0, 50),
|
|
NewLocation(2, 150.0, 250.0, 350.0, 50),
|
|
}
|
|
quantity := int32(1)
|
|
maxVariation := float32(5.0)
|
|
|
|
step := NewQuestStep(id, stepType, description, nil, quantity, "", locations, maxVariation, 100.0, 0)
|
|
if step == nil {
|
|
t.Fatal("NewQuestStep returned nil")
|
|
}
|
|
|
|
// Test locations were copied
|
|
if len(step.Locations) != len(locations) {
|
|
t.Errorf("Expected %d locations, got %d", len(locations), len(step.Locations))
|
|
}
|
|
|
|
// Test IDs map should be nil for location steps
|
|
if step.IDs != nil {
|
|
t.Error("Expected IDs to be nil for location step")
|
|
}
|
|
}
|
|
|
|
func TestQuestStepProgress(t *testing.T) {
|
|
step := NewQuestStep(1, StepTypeKill, "Kill goblins", []int32{100}, 5, "", nil, 0, 100.0, 0)
|
|
|
|
// Test initial state
|
|
if step.Complete() {
|
|
t.Error("New step should not be complete")
|
|
}
|
|
if step.GetStepProgress() != 0 {
|
|
t.Error("New step should have 0 progress")
|
|
}
|
|
|
|
// Test adding progress
|
|
added := step.AddStepProgress(2)
|
|
if added != 2 {
|
|
t.Errorf("Expected 2 progress added, got %d", added)
|
|
}
|
|
if step.GetStepProgress() != 2 {
|
|
t.Errorf("Expected progress 2, got %d", step.GetStepProgress())
|
|
}
|
|
if !step.WasUpdated() {
|
|
t.Error("Step should be marked as updated")
|
|
}
|
|
|
|
// Test completing step
|
|
added = step.AddStepProgress(5) // Should cap at quantity (5)
|
|
if added != 3 {
|
|
t.Errorf("Expected 3 progress added (to reach cap), got %d", added)
|
|
}
|
|
if step.GetStepProgress() != 5 {
|
|
t.Errorf("Expected progress 5, got %d", step.GetStepProgress())
|
|
}
|
|
if !step.Complete() {
|
|
t.Error("Step should be complete")
|
|
}
|
|
|
|
// Test setting complete directly
|
|
step2 := NewQuestStep(2, StepTypeChat, "Talk to NPC", []int32{200}, 1, "", nil, 0, 100.0, 0)
|
|
step2.SetComplete()
|
|
if !step2.Complete() {
|
|
t.Error("Step should be complete after SetComplete")
|
|
}
|
|
if step2.GetStepProgress() != step2.Quantity {
|
|
t.Error("Step progress should equal quantity after SetComplete")
|
|
}
|
|
}
|
|
|
|
func TestQuestStepReferencedID(t *testing.T) {
|
|
ids := []int32{100, 101, 102}
|
|
step := NewQuestStep(1, StepTypeKill, "Kill goblins", ids, 5, "", nil, 0, 100.0, 0)
|
|
|
|
// Test referenced IDs
|
|
for _, id := range ids {
|
|
if !step.CheckStepReferencedID(id) {
|
|
t.Errorf("Expected ID %d to be referenced", id)
|
|
}
|
|
}
|
|
|
|
// Test non-referenced ID
|
|
if step.CheckStepReferencedID(999) {
|
|
t.Error("Expected ID 999 to not be referenced")
|
|
}
|
|
}
|
|
|
|
func TestQuestStepLocationUpdate(t *testing.T) {
|
|
locations := []*Location{
|
|
NewLocation(1, 100.0, 200.0, 300.0, 50),
|
|
}
|
|
maxVariation := float32(5.0)
|
|
step := NewQuestStep(1, StepTypeLocation, "Visit location", nil, 1, "", locations, maxVariation, 100.0, 0)
|
|
|
|
// Test exact location match
|
|
if !step.CheckStepLocationUpdate(100.0, 200.0, 300.0, 50) {
|
|
t.Error("Should match exact location")
|
|
}
|
|
|
|
// Test location within variation (total diff = 2+2+2 = 6, which is > 5.0 maxVariation)
|
|
// Need smaller differences: 1+1+1 = 3, which is < 5.0
|
|
if !step.CheckStepLocationUpdate(101.0, 201.0, 301.0, 50) {
|
|
t.Error("Should match location within variation")
|
|
}
|
|
|
|
// Test location outside variation
|
|
if step.CheckStepLocationUpdate(110.0, 210.0, 310.0, 50) {
|
|
t.Error("Should not match location outside variation")
|
|
}
|
|
|
|
// Test wrong zone
|
|
if step.CheckStepLocationUpdate(100.0, 200.0, 300.0, 99) {
|
|
t.Error("Should not match location in wrong zone")
|
|
}
|
|
}
|
|
|
|
func TestQuestStepCopy(t *testing.T) {
|
|
ids := []int32{100, 101}
|
|
locations := []*Location{
|
|
NewLocation(1, 50.0, 60.0, 70.0, 25),
|
|
}
|
|
original := NewQuestStep(1, StepTypeKill, "Original step", ids, 10, "Task Group", locations, 5.0, 75.0, 123)
|
|
original.SetStepProgress(3) // Add some progress
|
|
original.SetWasUpdated(true)
|
|
original.SetUpdateName("Test Update")
|
|
|
|
copied := original.Copy()
|
|
if copied == nil {
|
|
t.Fatal("Copy returned nil")
|
|
}
|
|
|
|
// Test basic properties were copied
|
|
if copied.ID != original.ID {
|
|
t.Error("Copied step should have same ID")
|
|
}
|
|
if copied.Type != original.Type {
|
|
t.Error("Copied step should have same Type")
|
|
}
|
|
if copied.Description != original.Description {
|
|
t.Error("Copied step should have same Description")
|
|
}
|
|
if copied.TaskGroup != original.TaskGroup {
|
|
t.Error("Copied step should have same TaskGroup")
|
|
}
|
|
if copied.Quantity != original.Quantity {
|
|
t.Error("Copied step should have same Quantity")
|
|
}
|
|
|
|
// Test progress was reset
|
|
if copied.StepProgress != 0 {
|
|
t.Error("Copied step progress should be reset to 0")
|
|
}
|
|
if copied.Updated != false {
|
|
t.Error("Copied step Updated flag should be reset to false")
|
|
}
|
|
|
|
// Test IDs map was copied
|
|
if len(copied.IDs) != len(original.IDs) {
|
|
t.Error("Copied step should have same number of IDs")
|
|
}
|
|
for id := range original.IDs {
|
|
if !copied.IDs[id] {
|
|
t.Errorf("Copied step should have ID %d", id)
|
|
}
|
|
}
|
|
|
|
// Test independence
|
|
copied.AddStepProgress(5)
|
|
if original.GetStepProgress() != 3 {
|
|
t.Error("Original step should not be affected by changes to copy")
|
|
}
|
|
}
|
|
|
|
func TestQuestStepGettersSetters(t *testing.T) {
|
|
step := NewQuestStep(1, StepTypeKill, "Test step", []int32{100}, 5, "", nil, 0, 100.0, 0)
|
|
|
|
// Test quantity getters
|
|
if step.GetCurrentQuantity() != 0 {
|
|
t.Error("Initial current quantity should be 0")
|
|
}
|
|
if step.GetNeededQuantity() != 5 {
|
|
t.Error("Needed quantity should match step quantity")
|
|
}
|
|
|
|
// Test setters
|
|
step.SetDescription("New description")
|
|
if step.Description != "New description" {
|
|
t.Error("Description should be updated")
|
|
}
|
|
|
|
step.SetTaskGroup("New Task Group")
|
|
if step.TaskGroup != "New Task Group" {
|
|
t.Error("Task group should be updated")
|
|
}
|
|
|
|
step.SetUpdateName("Update Name")
|
|
if step.UpdateName != "Update Name" {
|
|
t.Error("Update name should be updated")
|
|
}
|
|
|
|
step.SetUpdateTargetName("Target Name")
|
|
if step.UpdateTargetName != "Target Name" {
|
|
t.Error("Update target name should be updated")
|
|
}
|
|
|
|
step.SetIcon(42)
|
|
if step.Icon != 42 {
|
|
t.Error("Icon should be updated")
|
|
}
|
|
|
|
// Test reset task group
|
|
step.ResetTaskGroup()
|
|
if step.TaskGroup != "" {
|
|
t.Error("Task group should be empty after reset")
|
|
}
|
|
}
|
|
|
|
// Test Quest functionality
|
|
func TestNewQuest(t *testing.T) {
|
|
id := int32(1001)
|
|
quest := NewQuest(id)
|
|
if quest == nil {
|
|
t.Fatal("NewQuest returned nil")
|
|
}
|
|
|
|
if quest.ID != id {
|
|
t.Errorf("Expected ID %d, got %d", id, quest.ID)
|
|
}
|
|
|
|
// Test defaults
|
|
if quest.PrereqLevel != DefaultPrereqLevel {
|
|
t.Errorf("Expected PrereqLevel %d, got %d", DefaultPrereqLevel, quest.PrereqLevel)
|
|
}
|
|
if quest.TaskGroupNum != DefaultTaskGroupNum {
|
|
t.Errorf("Expected TaskGroupNum %d, got %d", DefaultTaskGroupNum, quest.TaskGroupNum)
|
|
}
|
|
if quest.Visible != DefaultVisible {
|
|
t.Errorf("Expected Visible %d, got %d", DefaultVisible, quest.Visible)
|
|
}
|
|
|
|
// Test maps are initialized
|
|
if quest.QuestStepMap == nil {
|
|
t.Error("QuestStepMap should be initialized")
|
|
}
|
|
if quest.QuestStepReverseMap == nil {
|
|
t.Error("QuestStepReverseMap should be initialized")
|
|
}
|
|
if quest.TaskGroupOrder == nil {
|
|
t.Error("TaskGroupOrder should be initialized")
|
|
}
|
|
if quest.TaskGroup == nil {
|
|
t.Error("TaskGroup should be initialized")
|
|
}
|
|
if quest.CompleteActions == nil {
|
|
t.Error("CompleteActions should be initialized")
|
|
}
|
|
if quest.ProgressActions == nil {
|
|
t.Error("ProgressActions should be initialized")
|
|
}
|
|
if quest.FailedActions == nil {
|
|
t.Error("FailedActions should be initialized")
|
|
}
|
|
if quest.RewardFactions == nil {
|
|
t.Error("RewardFactions should be initialized")
|
|
}
|
|
|
|
// Test date fields
|
|
now := time.Now()
|
|
if quest.Day != int8(now.Day()) {
|
|
t.Error("Day should be set to current day")
|
|
}
|
|
if quest.Month != int8(now.Month()) {
|
|
t.Error("Month should be set to current month")
|
|
}
|
|
if quest.Year != int8(now.Year()-2000) {
|
|
t.Error("Year should be set to current year - 2000")
|
|
}
|
|
}
|
|
|
|
func TestQuestRegisterQuest(t *testing.T) {
|
|
quest := NewQuest(1001)
|
|
name := "The Great Adventure"
|
|
questType := "Signature"
|
|
zone := "commonlands"
|
|
level := int8(25)
|
|
description := "A quest of epic proportions"
|
|
|
|
quest.RegisterQuest(name, questType, zone, level, description)
|
|
|
|
if quest.Name != name {
|
|
t.Errorf("Expected Name '%s', got '%s'", name, quest.Name)
|
|
}
|
|
if quest.Type != questType {
|
|
t.Errorf("Expected Type '%s', got '%s'", questType, quest.Type)
|
|
}
|
|
if quest.Zone != zone {
|
|
t.Errorf("Expected Zone '%s', got '%s'", zone, quest.Zone)
|
|
}
|
|
if quest.Level != level {
|
|
t.Errorf("Expected Level %d, got %d", level, quest.Level)
|
|
}
|
|
if quest.Description != description {
|
|
t.Errorf("Expected Description '%s', got '%s'", description, quest.Description)
|
|
}
|
|
if !quest.NeedsSave {
|
|
t.Error("NeedsSave should be true after RegisterQuest")
|
|
}
|
|
}
|
|
|
|
func TestQuestAddRemoveSteps(t *testing.T) {
|
|
quest := NewQuest(1001)
|
|
|
|
// Test adding steps
|
|
step1 := NewQuestStep(1, StepTypeKill, "Kill goblins", []int32{100}, 5, "Combat", nil, 0, 100.0, 0)
|
|
step2 := NewQuestStep(2, StepTypeChat, "Talk to NPC", []int32{200}, 1, "Social", nil, 0, 100.0, 0)
|
|
|
|
if !quest.AddQuestStep(step1) {
|
|
t.Error("Should be able to add first step")
|
|
}
|
|
if !quest.AddQuestStep(step2) {
|
|
t.Error("Should be able to add second step")
|
|
}
|
|
|
|
// Test duplicate step ID
|
|
duplicate := NewQuestStep(1, StepTypeObtainItem, "Get item", []int32{300}, 1, "", nil, 0, 100.0, 0)
|
|
if quest.AddQuestStep(duplicate) {
|
|
t.Error("Should not be able to add step with duplicate ID")
|
|
}
|
|
|
|
// Test quest step tracking
|
|
if len(quest.QuestSteps) != 2 {
|
|
t.Errorf("Expected 2 steps, got %d", len(quest.QuestSteps))
|
|
}
|
|
if len(quest.QuestStepMap) != 2 {
|
|
t.Errorf("Expected 2 steps in map, got %d", len(quest.QuestStepMap))
|
|
}
|
|
if len(quest.QuestStepReverseMap) != 2 {
|
|
t.Errorf("Expected 2 steps in reverse map, got %d", len(quest.QuestStepReverseMap))
|
|
}
|
|
|
|
// Test task groups
|
|
if len(quest.TaskGroup) != 2 {
|
|
t.Errorf("Expected 2 task groups, got %d", len(quest.TaskGroup))
|
|
}
|
|
|
|
// Test getting step
|
|
retrieved := quest.GetQuestStep(1)
|
|
if retrieved != step1 {
|
|
t.Error("GetQuestStep should return the correct step")
|
|
}
|
|
|
|
// Test removing step
|
|
if !quest.RemoveQuestStep(1) {
|
|
t.Error("Should be able to remove existing step")
|
|
}
|
|
if quest.RemoveQuestStep(999) {
|
|
t.Error("Should not be able to remove non-existent step")
|
|
}
|
|
|
|
// Test step was removed from all tracking
|
|
if len(quest.QuestSteps) != 1 {
|
|
t.Error("Step should be removed from slice")
|
|
}
|
|
if quest.GetQuestStep(1) != nil {
|
|
t.Error("Step should not be found after removal")
|
|
}
|
|
if quest.QuestStepMap[1] != nil {
|
|
t.Error("Step should be removed from map")
|
|
}
|
|
}
|
|
|
|
func TestQuestCreateStep(t *testing.T) {
|
|
quest := NewQuest(1001)
|
|
|
|
step := quest.CreateQuestStep(1, StepTypeKill, "Kill monsters", []int32{100, 101}, 3, "Combat", nil, 0, 100.0, 0)
|
|
if step == nil {
|
|
t.Fatal("CreateQuestStep should return created step")
|
|
}
|
|
|
|
if step.ID != 1 {
|
|
t.Error("Created step should have correct ID")
|
|
}
|
|
if quest.GetQuestStep(1) != step {
|
|
t.Error("Created step should be added to quest")
|
|
}
|
|
|
|
// Test creating step with duplicate ID
|
|
duplicate := quest.CreateQuestStep(1, StepTypeChat, "Talk", []int32{200}, 1, "", nil, 0, 100.0, 0)
|
|
if duplicate != nil {
|
|
t.Error("Should not be able to create step with duplicate ID")
|
|
}
|
|
}
|
|
|
|
func TestQuestStepCompletion(t *testing.T) {
|
|
quest := NewQuest(1001)
|
|
step := NewQuestStep(1, StepTypeKill, "Kill goblins", []int32{100}, 3, "", nil, 0, 100.0, 0)
|
|
quest.AddQuestStep(step)
|
|
|
|
// Test setting step complete
|
|
if !quest.SetStepComplete(1) {
|
|
t.Error("Should be able to complete step")
|
|
}
|
|
if !quest.GetQuestStepCompleted(1) {
|
|
t.Error("Step should be marked as completed")
|
|
}
|
|
if quest.SetStepComplete(1) {
|
|
t.Error("Should not be able to complete already completed step")
|
|
}
|
|
|
|
// Test completing non-existent step
|
|
if quest.SetStepComplete(999) {
|
|
t.Error("Should not be able to complete non-existent step")
|
|
}
|
|
|
|
// Test quest is complete
|
|
if !quest.GetCompleted() {
|
|
t.Error("Quest should be complete when all steps are complete")
|
|
}
|
|
}
|
|
|
|
func TestQuestCurrentStep(t *testing.T) {
|
|
quest := NewQuest(1001)
|
|
step1 := NewQuestStep(1, StepTypeKill, "Kill", []int32{100}, 1, "", nil, 0, 100.0, 0)
|
|
step2 := NewQuestStep(2, StepTypeChat, "Chat", []int32{200}, 1, "", nil, 0, 100.0, 0)
|
|
quest.AddQuestStep(step1)
|
|
quest.AddQuestStep(step2)
|
|
|
|
// Test first incomplete step
|
|
current := quest.GetCurrentQuestStep()
|
|
if current != 1 {
|
|
t.Errorf("Expected current step 1, got %d", current)
|
|
}
|
|
|
|
// Test step is active
|
|
if !quest.QuestStepIsActive(1) {
|
|
t.Error("Step 1 should be active")
|
|
}
|
|
if !quest.QuestStepIsActive(2) {
|
|
t.Error("Step 2 should be active")
|
|
}
|
|
|
|
// Complete first step
|
|
quest.SetStepComplete(1)
|
|
|
|
// Test next step becomes current
|
|
current = quest.GetCurrentQuestStep()
|
|
if current != 2 {
|
|
t.Errorf("Expected current step 2, got %d", current)
|
|
}
|
|
|
|
// Test completed step is not active
|
|
if quest.QuestStepIsActive(1) {
|
|
t.Error("Step 1 should not be active after completion")
|
|
}
|
|
|
|
// Complete all steps
|
|
quest.SetStepComplete(2)
|
|
|
|
// Test no current step when all complete
|
|
current = quest.GetCurrentQuestStep()
|
|
if current != 0 {
|
|
t.Errorf("Expected current step 0 when all complete, got %d", current)
|
|
}
|
|
}
|
|
|
|
func TestQuestKillUpdate(t *testing.T) {
|
|
quest := NewQuest(1001)
|
|
killStep := NewQuestStep(1, StepTypeKill, "Kill goblins", []int32{100, 101}, 2, "", nil, 0, 100.0, 0)
|
|
otherStep := NewQuestStep(2, StepTypeChat, "Chat with NPC", []int32{200}, 1, "", nil, 0, 100.0, 0)
|
|
quest.AddQuestStep(killStep)
|
|
quest.AddQuestStep(otherStep)
|
|
|
|
// Test checking for kill updates
|
|
if !quest.CheckQuestReferencedSpawns(100) {
|
|
t.Error("Should reference spawn 100")
|
|
}
|
|
if !quest.CheckQuestReferencedSpawns(101) {
|
|
t.Error("Should reference spawn 101")
|
|
}
|
|
if quest.CheckQuestReferencedSpawns(999) {
|
|
t.Error("Should not reference spawn 999")
|
|
}
|
|
|
|
// Test kill update without applying
|
|
if !quest.CheckQuestKillUpdate(100, false) {
|
|
t.Error("Should detect kill update for spawn 100")
|
|
}
|
|
if quest.GetStepProgress(1) != 0 {
|
|
t.Error("Progress should not change when update=false")
|
|
}
|
|
|
|
// Test kill update with applying
|
|
if !quest.CheckQuestKillUpdate(100, true) {
|
|
t.Error("Should process kill update for spawn 100")
|
|
}
|
|
if quest.GetStepProgress(1) != 1 {
|
|
t.Error("Progress should increase after kill update")
|
|
}
|
|
|
|
// Test kill update for non-referenced spawn
|
|
if quest.CheckQuestKillUpdate(999, true) {
|
|
t.Error("Should not process kill update for non-referenced spawn")
|
|
}
|
|
}
|
|
|
|
func TestQuestChatUpdate(t *testing.T) {
|
|
quest := NewQuest(1001)
|
|
chatStep := NewQuestStep(1, StepTypeChat, "Talk to NPC", []int32{200}, 1, "", nil, 0, 100.0, 0)
|
|
quest.AddQuestStep(chatStep)
|
|
|
|
// Test chat update
|
|
if !quest.CheckQuestChatUpdate(200, true) {
|
|
t.Error("Should process chat update for NPC 200")
|
|
}
|
|
if quest.GetStepProgress(1) != 1 {
|
|
t.Error("Progress should increase after chat update")
|
|
}
|
|
|
|
// Test chat update for non-referenced NPC
|
|
if quest.CheckQuestChatUpdate(999, true) {
|
|
t.Error("Should not process chat update for non-referenced NPC")
|
|
}
|
|
}
|
|
|
|
func TestQuestItemUpdate(t *testing.T) {
|
|
quest := NewQuest(1001)
|
|
itemStep := NewQuestStep(1, StepTypeObtainItem, "Get items", []int32{300}, 5, "", nil, 0, 100.0, 0)
|
|
quest.AddQuestStep(itemStep)
|
|
|
|
// Test item update
|
|
if !quest.CheckQuestItemUpdate(300, 3) {
|
|
t.Error("Should process item update for item 300")
|
|
}
|
|
if quest.GetStepProgress(1) != 3 {
|
|
t.Error("Progress should increase by item quantity")
|
|
}
|
|
|
|
// Test item update for non-referenced item
|
|
if quest.CheckQuestItemUpdate(999, 1) {
|
|
t.Error("Should not process item update for non-referenced item")
|
|
}
|
|
}
|
|
|
|
func TestQuestLocationUpdate(t *testing.T) {
|
|
quest := NewQuest(1001)
|
|
locations := []*Location{
|
|
NewLocation(1, 100.0, 200.0, 300.0, 50),
|
|
}
|
|
locationStep := NewQuestStep(1, StepTypeLocation, "Visit location", nil, 1, "", locations, 5.0, 100.0, 0)
|
|
quest.AddQuestStep(locationStep)
|
|
|
|
// Test location update (use smaller differences to stay within 5.0 total variation)
|
|
if !quest.CheckQuestLocationUpdate(101.0, 201.0, 301.0, 50) {
|
|
t.Error("Should process location update for nearby coordinates")
|
|
}
|
|
if quest.GetStepProgress(1) != 1 {
|
|
t.Error("Progress should increase after location update")
|
|
}
|
|
|
|
// Test location update for far coordinates
|
|
if quest.CheckQuestLocationUpdate(200.0, 300.0, 400.0, 50) {
|
|
t.Error("Should not process location update for far coordinates")
|
|
}
|
|
}
|
|
|
|
func TestQuestSpellUpdate(t *testing.T) {
|
|
quest := NewQuest(1001)
|
|
spellStep := NewQuestStep(1, StepTypeSpell, "Cast spell", []int32{400}, 3, "", nil, 0, 100.0, 0)
|
|
quest.AddQuestStep(spellStep)
|
|
|
|
// Test spell update
|
|
if !quest.CheckQuestSpellUpdate(400) {
|
|
t.Error("Should process spell update for spell 400")
|
|
}
|
|
if quest.GetStepProgress(1) != 1 {
|
|
t.Error("Progress should increase after spell update")
|
|
}
|
|
|
|
// Test spell update for non-referenced spell
|
|
if quest.CheckQuestSpellUpdate(999) {
|
|
t.Error("Should not process spell update for non-referenced spell")
|
|
}
|
|
}
|
|
|
|
func TestQuestRefIDUpdate(t *testing.T) {
|
|
quest := NewQuest(1001)
|
|
harvestStep := NewQuestStep(1, StepTypeHarvest, "Harvest resources", []int32{500}, 10, "", nil, 0, 100.0, 0)
|
|
craftStep := NewQuestStep(2, StepTypeCraft, "Craft items", []int32{600}, 5, "", nil, 0, 100.0, 0)
|
|
quest.AddQuestStep(harvestStep)
|
|
quest.AddQuestStep(craftStep)
|
|
|
|
// Test harvest update
|
|
if !quest.CheckQuestRefIDUpdate(500, 3) {
|
|
t.Error("Should process harvest update for ref 500")
|
|
}
|
|
if quest.GetStepProgress(1) != 3 {
|
|
t.Error("Harvest progress should increase")
|
|
}
|
|
|
|
// Test craft update
|
|
if !quest.CheckQuestRefIDUpdate(600, 2) {
|
|
t.Error("Should process craft update for ref 600")
|
|
}
|
|
if quest.GetStepProgress(2) != 2 {
|
|
t.Error("Craft progress should increase")
|
|
}
|
|
|
|
// Test update for non-referenced ref
|
|
if quest.CheckQuestRefIDUpdate(999, 1) {
|
|
t.Error("Should not process update for non-referenced ref")
|
|
}
|
|
}
|
|
|
|
func TestQuestTaskGroups(t *testing.T) {
|
|
quest := NewQuest(1001)
|
|
step1 := NewQuestStep(1, StepTypeKill, "Kill 1", []int32{100}, 1, "Group A", nil, 0, 100.0, 0)
|
|
step2 := NewQuestStep(2, StepTypeKill, "Kill 2", []int32{101}, 1, "Group A", nil, 0, 100.0, 0)
|
|
step3 := NewQuestStep(3, StepTypeChat, "Chat", []int32{200}, 1, "Group B", nil, 0, 100.0, 0)
|
|
|
|
quest.AddQuestStep(step1)
|
|
quest.AddQuestStep(step2)
|
|
quest.AddQuestStep(step3)
|
|
|
|
// Test task groups were created
|
|
if len(quest.TaskGroup) != 2 {
|
|
t.Errorf("Expected 2 task groups, got %d", len(quest.TaskGroup))
|
|
}
|
|
if len(quest.TaskGroup["Group A"]) != 2 {
|
|
t.Errorf("Expected 2 steps in Group A, got %d", len(quest.TaskGroup["Group A"]))
|
|
}
|
|
if len(quest.TaskGroup["Group B"]) != 1 {
|
|
t.Errorf("Expected 1 step in Group B, got %d", len(quest.TaskGroup["Group B"]))
|
|
}
|
|
|
|
// Test task group order
|
|
if len(quest.TaskGroupOrder) != 2 {
|
|
t.Errorf("Expected 2 task group orders, got %d", len(quest.TaskGroupOrder))
|
|
}
|
|
|
|
// Test getting current task group step
|
|
current := quest.GetTaskGroupStep()
|
|
if current != 1 { // Should be first group
|
|
t.Errorf("Expected task group step 1, got %d", current)
|
|
}
|
|
|
|
// Complete first group
|
|
quest.SetStepComplete(1)
|
|
quest.SetStepComplete(2)
|
|
|
|
// Should move to next group
|
|
current = quest.GetTaskGroupStep()
|
|
if current != 2 {
|
|
t.Errorf("Expected task group step 2 after completing first group, got %d", current)
|
|
}
|
|
}
|
|
|
|
func TestQuestCategoryYellow(t *testing.T) {
|
|
quest := NewQuest(1001)
|
|
|
|
// Test yellow categories
|
|
yellowTypes := []string{"Signature", "Heritage", "Hallmark", "Deity", "Miscellaneous", "Language", "Lore and Legend", "World Event", "Tradeskill"}
|
|
for _, questType := range yellowTypes {
|
|
quest.Type = questType
|
|
if !quest.CheckCategoryYellow() {
|
|
t.Errorf("Quest type '%s' should be yellow", questType)
|
|
}
|
|
|
|
// Test case insensitive
|
|
quest.Type = strings.ToLower(questType)
|
|
if !quest.CheckCategoryYellow() {
|
|
t.Errorf("Quest type '%s' (lowercase) should be yellow", questType)
|
|
}
|
|
}
|
|
|
|
// Test non-yellow category
|
|
quest.Type = "Random"
|
|
if quest.CheckCategoryYellow() {
|
|
t.Error("Quest type 'Random' should not be yellow")
|
|
}
|
|
}
|
|
|
|
func TestQuestTimer(t *testing.T) {
|
|
quest := NewQuest(1001)
|
|
|
|
// Test setting timer
|
|
duration := int32(3600) // 1 hour
|
|
quest.SetStepTimer(duration)
|
|
|
|
expectedTime := int32(time.Now().Unix()) + duration
|
|
if quest.Timestamp < expectedTime-1 || quest.Timestamp > expectedTime+1 {
|
|
t.Error("Timer should be set to approximately current time + duration")
|
|
}
|
|
|
|
// Test clearing timer
|
|
quest.SetStepTimer(0)
|
|
if quest.Timestamp != 0 {
|
|
t.Error("Timer should be cleared when duration is 0")
|
|
}
|
|
}
|
|
|
|
func TestQuestTemporaryState(t *testing.T) {
|
|
quest := NewQuest(1001)
|
|
quest.TmpRewardCoins = 1000
|
|
quest.TmpRewardStatus = 500
|
|
|
|
// Test setting temporary state
|
|
quest.SetQuestTemporaryState(true, "Temporary description")
|
|
if !quest.QuestStateTemporary {
|
|
t.Error("Quest should be in temporary state")
|
|
}
|
|
if quest.QuestTempDescription != "Temporary description" {
|
|
t.Error("Temporary description should be set")
|
|
}
|
|
|
|
// Test clearing temporary state
|
|
quest.SetQuestTemporaryState(false, "")
|
|
if quest.QuestStateTemporary {
|
|
t.Error("Quest should not be in temporary state")
|
|
}
|
|
if quest.TmpRewardCoins != 0 {
|
|
t.Error("Temporary coins should be cleared")
|
|
}
|
|
if quest.TmpRewardStatus != 0 {
|
|
t.Error("Temporary status should be cleared")
|
|
}
|
|
}
|
|
|
|
func TestQuestShareCriteria(t *testing.T) {
|
|
quest := NewQuest(1001)
|
|
|
|
// Test no sharing allowed
|
|
quest.QuestShareableFlag = ShareableNone
|
|
if quest.CanShareQuestCriteria(false, false, 1) {
|
|
t.Error("Should not be able to share when flag is ShareableNone")
|
|
}
|
|
|
|
// Test sharing active quests
|
|
quest.QuestShareableFlag = ShareableActive
|
|
if !quest.CanShareQuestCriteria(true, false, 1) {
|
|
t.Error("Should be able to share active quest")
|
|
}
|
|
if quest.CanShareQuestCriteria(false, false, 1) {
|
|
t.Error("Should not be able to share when player doesn't have quest")
|
|
}
|
|
|
|
// Test sharing during quest - ShareableDuring allows sharing when step > 1
|
|
// but also needs ShareableActive to allow sharing when hasQuest=true
|
|
quest.QuestShareableFlag = ShareableActive | ShareableDuring
|
|
if !quest.CanShareQuestCriteria(true, false, 2) {
|
|
t.Error("Should be able to share during quest")
|
|
}
|
|
// With ShareableDuring, step 1 is NOT > 1, so the ShareableDuring condition doesn't apply
|
|
// The ShareableActive flag allows sharing of active quests regardless of step
|
|
// So this test expectation might be wrong - let's check if it actually CAN be shared
|
|
if !quest.CanShareQuestCriteria(true, false, 1) {
|
|
t.Error("Should be able to share active quest at any step with ShareableActive")
|
|
}
|
|
|
|
// Test sharing completed quests
|
|
quest.QuestShareableFlag = ShareableCompleted
|
|
if !quest.CanShareQuestCriteria(false, true, 1) {
|
|
t.Error("Should be able to share completed quest")
|
|
}
|
|
if quest.CanShareQuestCriteria(false, false, 1) {
|
|
t.Error("Should not be able to share uncompleted quest when only completed sharing allowed")
|
|
}
|
|
}
|
|
|
|
func TestQuestCopy(t *testing.T) {
|
|
// Create original quest with comprehensive data
|
|
original := NewQuest(1001)
|
|
original.RegisterQuest("Test Quest", "Signature", "testzone", 25, "A test quest")
|
|
original.QuestGiver = 100
|
|
original.ReturnID = 101
|
|
original.PrereqLevel = 20
|
|
original.PrereqRaces = []int8{1, 2, 3}
|
|
original.PrereqClasses = []int8{4, 5, 6}
|
|
original.PrereqFactions = []*QuestFactionPrereq{
|
|
NewQuestFactionPrereq(1, 100, 1000),
|
|
}
|
|
original.RewardCoins = 5000
|
|
original.RewardExp = 10000
|
|
original.RewardFactions[1] = 500
|
|
original.Repeatable = true
|
|
original.CompleteAction = "test_complete.lua"
|
|
|
|
// Add steps
|
|
step1 := NewQuestStep(1, StepTypeKill, "Kill goblins", []int32{100}, 5, "Combat", nil, 0, 90.0, 0)
|
|
step2 := NewQuestStep(2, StepTypeChat, "Talk to NPC", []int32{200}, 1, "Social", nil, 0, 100.0, 0)
|
|
original.AddQuestStep(step1)
|
|
original.AddQuestStep(step2)
|
|
|
|
// Add actions
|
|
original.CompleteActions[1] = "kill_complete.lua"
|
|
original.ProgressActions[1] = "kill_progress.lua"
|
|
original.FailedActions[1] = "kill_failed.lua"
|
|
|
|
// Set some progress and state
|
|
original.AddStepProgress(1, 2)
|
|
original.TurnedIn = true
|
|
original.Deleted = true
|
|
|
|
// Create copy
|
|
copied := original.Copy()
|
|
if copied == nil {
|
|
t.Fatal("Copy returned nil")
|
|
}
|
|
|
|
// Test basic properties were copied
|
|
if copied.ID != original.ID {
|
|
t.Error("Copied quest should have same ID")
|
|
}
|
|
if copied.Name != original.Name {
|
|
t.Error("Copied quest should have same Name")
|
|
}
|
|
if copied.Type != original.Type {
|
|
t.Error("Copied quest should have same Type")
|
|
}
|
|
if copied.Zone != original.Zone {
|
|
t.Error("Copied quest should have same Zone")
|
|
}
|
|
if copied.Level != original.Level {
|
|
t.Error("Copied quest should have same Level")
|
|
}
|
|
|
|
// Test prerequisites were copied
|
|
if copied.PrereqLevel != original.PrereqLevel {
|
|
t.Error("Copied quest should have same PrereqLevel")
|
|
}
|
|
if len(copied.PrereqRaces) != len(original.PrereqRaces) {
|
|
t.Error("Copied quest should have same PrereqRaces length")
|
|
}
|
|
if len(copied.PrereqFactions) != len(original.PrereqFactions) {
|
|
t.Error("Copied quest should have same PrereqFactions length")
|
|
}
|
|
|
|
// Test rewards were copied
|
|
if copied.RewardCoins != original.RewardCoins {
|
|
t.Error("Copied quest should have same RewardCoins")
|
|
}
|
|
if copied.RewardExp != original.RewardExp {
|
|
t.Error("Copied quest should have same RewardExp")
|
|
}
|
|
if copied.RewardFactions[1] != original.RewardFactions[1] {
|
|
t.Error("Copied quest should have same faction rewards")
|
|
}
|
|
|
|
// Test steps were copied
|
|
if len(copied.QuestSteps) != len(original.QuestSteps) {
|
|
t.Error("Copied quest should have same number of steps")
|
|
}
|
|
if len(copied.QuestStepMap) != len(original.QuestStepMap) {
|
|
t.Error("Copied quest should have same step map size")
|
|
}
|
|
|
|
// Test actions were copied
|
|
if copied.CompleteActions[1] != original.CompleteActions[1] {
|
|
t.Error("Copied quest should have same complete actions")
|
|
}
|
|
|
|
// Test state was reset
|
|
if copied.TurnedIn {
|
|
t.Error("Copied quest TurnedIn should be reset")
|
|
}
|
|
if copied.Deleted {
|
|
t.Error("Copied quest Deleted should be reset")
|
|
}
|
|
if !copied.UpdateNeeded {
|
|
t.Error("Copied quest UpdateNeeded should be true")
|
|
}
|
|
|
|
// Test step progress was reset
|
|
copiedStep := copied.GetQuestStep(1)
|
|
if copiedStep.GetStepProgress() != 0 {
|
|
t.Error("Copied quest step progress should be reset")
|
|
}
|
|
|
|
// Test independence
|
|
copied.Name = "Modified Name"
|
|
if original.Name == "Modified Name" {
|
|
t.Error("Original quest should not be affected by changes to copy")
|
|
}
|
|
}
|
|
|
|
func TestQuestValidation(t *testing.T) {
|
|
// Test valid quest
|
|
quest := NewQuest(1001)
|
|
quest.RegisterQuest("Valid Quest", "Normal", "testzone", 25, "A valid quest")
|
|
step := NewQuestStep(1, StepTypeKill, "Kill monsters", []int32{100}, 5, "", nil, 0, 100.0, 0)
|
|
quest.AddQuestStep(step)
|
|
|
|
if err := quest.ValidateQuest(); err != nil {
|
|
t.Errorf("Valid quest should pass validation: %v", err)
|
|
}
|
|
|
|
// Test invalid quest ID
|
|
invalidQuest := NewQuest(-1)
|
|
if err := invalidQuest.ValidateQuest(); err == nil {
|
|
t.Error("Quest with negative ID should fail validation")
|
|
}
|
|
|
|
// Test missing name
|
|
quest.Name = ""
|
|
if err := quest.ValidateQuest(); err == nil {
|
|
t.Error("Quest with empty name should fail validation")
|
|
}
|
|
|
|
// Test name too long
|
|
quest.Name = strings.Repeat("a", MaxQuestNameLength+1)
|
|
if err := quest.ValidateQuest(); err == nil {
|
|
t.Error("Quest with too long name should fail validation")
|
|
}
|
|
|
|
// Test invalid level
|
|
quest.Name = "Valid Name"
|
|
quest.Level = 0
|
|
if err := quest.ValidateQuest(); err == nil {
|
|
t.Error("Quest with invalid level should fail validation")
|
|
}
|
|
|
|
quest.Level = 101
|
|
if err := quest.ValidateQuest(); err == nil {
|
|
t.Error("Quest with too high level should fail validation")
|
|
}
|
|
|
|
// Test quest without steps
|
|
quest.Level = 25
|
|
quest.QuestSteps = nil
|
|
if err := quest.ValidateQuest(); err == nil {
|
|
t.Error("Quest without steps should fail validation")
|
|
}
|
|
|
|
// Test invalid step
|
|
quest.AddQuestStep(step)
|
|
step.Quantity = -1
|
|
if err := quest.ValidateQuest(); err == nil {
|
|
t.Error("Quest with invalid step should fail validation")
|
|
}
|
|
}
|
|
|
|
// Test MasterQuestList functionality
|
|
func TestNewMasterQuestList(t *testing.T) {
|
|
mql := NewMasterQuestList()
|
|
if mql == nil {
|
|
t.Fatal("NewMasterQuestList returned nil")
|
|
}
|
|
|
|
if mql.quests == nil {
|
|
t.Error("Quests map should be initialized")
|
|
}
|
|
}
|
|
|
|
func TestMasterQuestListAddQuest(t *testing.T) {
|
|
mql := NewMasterQuestList()
|
|
quest := NewQuest(1001)
|
|
|
|
// Test adding valid quest
|
|
err := mql.AddQuest(1001, quest)
|
|
if err != nil {
|
|
t.Errorf("Should be able to add valid quest: %v", err)
|
|
}
|
|
|
|
// Test adding nil quest
|
|
err = mql.AddQuest(1002, nil)
|
|
if err == nil {
|
|
t.Error("Should not be able to add nil quest")
|
|
}
|
|
|
|
// Test ID mismatch
|
|
quest2 := NewQuest(1003)
|
|
err = mql.AddQuest(1004, quest2)
|
|
if err == nil {
|
|
t.Error("Should not be able to add quest with mismatched ID")
|
|
}
|
|
|
|
// Test duplicate quest
|
|
err = mql.AddQuest(1001, quest)
|
|
if err == nil {
|
|
t.Error("Should not be able to add duplicate quest")
|
|
}
|
|
}
|
|
|
|
func TestMasterQuestListGetQuest(t *testing.T) {
|
|
mql := NewMasterQuestList()
|
|
quest := NewQuest(1001)
|
|
quest.Name = "Original Quest"
|
|
mql.AddQuest(1001, quest)
|
|
|
|
// Test getting quest without copy
|
|
retrieved := mql.GetQuest(1001, false)
|
|
if retrieved != quest {
|
|
t.Error("Should return same quest instance when copyQuest=false")
|
|
}
|
|
|
|
// Test getting quest with copy
|
|
copied := mql.GetQuest(1001, true)
|
|
if copied == quest {
|
|
t.Error("Should return different instance when copyQuest=true")
|
|
}
|
|
if copied.ID != quest.ID {
|
|
t.Error("Copied quest should have same ID")
|
|
}
|
|
|
|
// Test getting non-existent quest
|
|
nonExistent := mql.GetQuest(9999, false)
|
|
if nonExistent != nil {
|
|
t.Error("Should return nil for non-existent quest")
|
|
}
|
|
}
|
|
|
|
func TestMasterQuestListHasQuest(t *testing.T) {
|
|
mql := NewMasterQuestList()
|
|
quest := NewQuest(1001)
|
|
mql.AddQuest(1001, quest)
|
|
|
|
if !mql.HasQuest(1001) {
|
|
t.Error("Should have quest 1001")
|
|
}
|
|
if mql.HasQuest(9999) {
|
|
t.Error("Should not have quest 9999")
|
|
}
|
|
}
|
|
|
|
func TestMasterQuestListRemoveQuest(t *testing.T) {
|
|
mql := NewMasterQuestList()
|
|
quest := NewQuest(1001)
|
|
mql.AddQuest(1001, quest)
|
|
|
|
// Test removing existing quest
|
|
if !mql.RemoveQuest(1001) {
|
|
t.Error("Should be able to remove existing quest")
|
|
}
|
|
if mql.HasQuest(1001) {
|
|
t.Error("Quest should be removed")
|
|
}
|
|
|
|
// Test removing non-existent quest
|
|
if mql.RemoveQuest(9999) {
|
|
t.Error("Should not be able to remove non-existent quest")
|
|
}
|
|
}
|
|
|
|
func TestMasterQuestListGetAllQuests(t *testing.T) {
|
|
mql := NewMasterQuestList()
|
|
quest1 := NewQuest(1001)
|
|
quest2 := NewQuest(1002)
|
|
mql.AddQuest(1001, quest1)
|
|
mql.AddQuest(1002, quest2)
|
|
|
|
allQuests := mql.GetAllQuests()
|
|
if len(allQuests) != 2 {
|
|
t.Errorf("Expected 2 quests, got %d", len(allQuests))
|
|
}
|
|
if allQuests[1001] != quest1 {
|
|
t.Error("Should return quest1")
|
|
}
|
|
if allQuests[1002] != quest2 {
|
|
t.Error("Should return quest2")
|
|
}
|
|
|
|
// Test independence of returned map
|
|
delete(allQuests, 1001)
|
|
if !mql.HasQuest(1001) {
|
|
t.Error("Original quest list should not be affected")
|
|
}
|
|
}
|
|
|
|
// Test utility functions and edge cases
|
|
func TestQuestStepEdgeCases(t *testing.T) {
|
|
// Test step with empty IDs for location type
|
|
locationStep := NewQuestStep(1, StepTypeLocation, "Visit", nil, 1, "", []*Location{}, 5.0, 100.0, 0)
|
|
if locationStep.IDs != nil {
|
|
t.Error("Location step should not have IDs map")
|
|
}
|
|
|
|
// Test step with empty locations for non-location type
|
|
killStep := NewQuestStep(2, StepTypeKill, "Kill", []int32{}, 1, "", nil, 0, 100.0, 0)
|
|
if killStep.Locations != nil {
|
|
t.Error("Non-location step should not have locations")
|
|
}
|
|
|
|
// Test step with percentage-based failure
|
|
chanceStep := NewQuestStep(3, StepTypeKill, "Maybe kill", []int32{100}, 5, "", nil, 0, 0.1, 0) // Very low success rate
|
|
initialProgress := chanceStep.GetStepProgress()
|
|
|
|
// Try multiple times, should eventually get some failures
|
|
attempts := 0
|
|
for attempts < 100 {
|
|
chanceStep.AddStepProgress(1)
|
|
attempts++
|
|
if chanceStep.GetStepProgress() == initialProgress {
|
|
break // Found a failure case
|
|
}
|
|
initialProgress = chanceStep.GetStepProgress()
|
|
}
|
|
// Note: This test is probabilistic, so we don't assert failure but just test the mechanism works
|
|
}
|
|
|
|
func TestQuestEdgeCases(t *testing.T) {
|
|
quest := NewQuest(1001)
|
|
|
|
// Test task group with empty name defaults to description
|
|
step := NewQuestStep(1, StepTypeKill, "Default Task Group", []int32{100}, 1, "", nil, 0, 100.0, 0)
|
|
quest.AddQuestStep(step)
|
|
|
|
if _, exists := quest.TaskGroup["Default Task Group"]; !exists {
|
|
t.Error("Empty task group should default to description")
|
|
}
|
|
|
|
// Test removing step - NOTE: Due to implementation bug, empty task groups are NOT removed
|
|
// because RemoveQuestStep only checks step.TaskGroup (which is empty) not the resolved name
|
|
quest.RemoveQuestStep(1)
|
|
if _, exists := quest.TaskGroup["Default Task Group"]; !exists {
|
|
t.Error("Task group still exists due to implementation limitation")
|
|
}
|
|
// The step was not actually removed from the task group due to the bug
|
|
if len(quest.TaskGroup["Default Task Group"]) != 1 {
|
|
t.Errorf("Expected task group to still contain 1 step due to bug, got %d", len(quest.TaskGroup["Default Task Group"]))
|
|
}
|
|
|
|
// Test completed step doesn't get updated
|
|
completedStep := NewQuestStep(2, StepTypeKill, "Completed", []int32{200}, 1, "", nil, 0, 100.0, 0)
|
|
quest.AddQuestStep(completedStep)
|
|
quest.SetStepComplete(2)
|
|
|
|
// Try to update completed step
|
|
if quest.CheckQuestKillUpdate(200, true) {
|
|
t.Error("Completed step should not be updated")
|
|
}
|
|
}
|
|
|
|
// Benchmark tests
|
|
func BenchmarkNewQuest(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
NewQuest(int32(i))
|
|
}
|
|
}
|
|
|
|
func BenchmarkQuestAddStep(b *testing.B) {
|
|
quest := NewQuest(1001)
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
step := NewQuestStep(int32(i), StepTypeKill, "Benchmark step", []int32{int32(i)}, 1, "", nil, 0, 100.0, 0)
|
|
quest.AddQuestStep(step)
|
|
}
|
|
}
|
|
|
|
func BenchmarkQuestStepProgress(b *testing.B) {
|
|
quest := NewQuest(1001)
|
|
step := NewQuestStep(1, StepTypeKill, "Benchmark", []int32{100}, int32(b.N), "", nil, 0, 100.0, 0)
|
|
quest.AddQuestStep(step)
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
quest.AddStepProgress(1, 1)
|
|
}
|
|
}
|
|
|
|
func BenchmarkQuestCopy(b *testing.B) {
|
|
quest := NewQuest(1001)
|
|
quest.RegisterQuest("Benchmark Quest", "Normal", "testzone", 25, "A quest for benchmarking")
|
|
|
|
// Add several steps
|
|
for i := 0; i < 10; i++ {
|
|
step := NewQuestStep(int32(i+1), StepTypeKill, fmt.Sprintf("Step %d", i+1), []int32{int32(100 + i)}, 5, "", nil, 0, 100.0, 0)
|
|
quest.AddQuestStep(step)
|
|
}
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
quest.Copy()
|
|
}
|
|
}
|
|
|
|
func BenchmarkMasterQuestListOperations(b *testing.B) {
|
|
mql := NewMasterQuestList()
|
|
|
|
// Pre-populate with quests
|
|
for i := 0; i < 1000; i++ {
|
|
quest := NewQuest(int32(i))
|
|
mql.AddQuest(int32(i), quest)
|
|
}
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
mql.GetQuest(int32(i%1000), false)
|
|
}
|
|
}
|