Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions _datafiles/guides/building/scripting/FUNCTIONS_ACTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ ActorObjects are the basic object that represents Users and NPCs
- [ActorObject.GetMobKills(mobId int) int](#actorobjectgetmobkillsmobid-int-int)
- [ActorObject.GetRaceKills(raceName string) int](#actorobjectgetracekillsracename-string-int)
- [ActorObject.GetHealth() int](#actorobjectgethealth-int)
- [ActorObject.SetHealth(amt int)](#actorobjectsethealthamt-int)
- [ActorObject.GetHealthMax() int](#actorobjectgethealthmax-int)
- [ActorObject.GetHealthPct() float](#actorobjectgethealthpct-float)
- [ActorObject.GetMana() int](#actorobjectgetmana-int)
Expand Down Expand Up @@ -87,6 +88,7 @@ ActorObjects are the basic object that represents Users and NPCs
- [ActorObject.TimerSet(name string, period string)](#actorobjecttimersetname-string-period-string)
- [ActorObject.TimerExpired(name string) bool](#actorobjecttimerexpiredname-string-bool)
- [ActorObject.TimerExists(name string) bool](#actorobjecttimerexistsname-string-bool)
- [ActorObject.AddEventLog(category string, message string)](#actorobjectaddeventlogcategory-string-message-string)



Expand Down Expand Up @@ -439,6 +441,14 @@ Returns the number of times the actor has killed a certain race of mob
## [ActorObject.GetHealth() int](/internal/scripting/actor_func.go)
Returns current actor health

## [ActorObject.SetHealth(amt int)](/internal/scripting/actor_func.go)
Sets actor health to a specific amount. If this exceeds their maximum health, sets to their maximum health.

| Argument | Explanation |
| --- | --- |
| amt | number of hitpoints to set them to |


## [ActorObject.GetHealthMax() int](/internal/scripting/actor_func.go)
Returns current actor max health

Expand Down Expand Up @@ -586,3 +596,10 @@ Returns true if the specified timer has expired or doesn't exist.
Returns true if the specified timer exists.
Set timers always exist until they are checked for expiration with `TimerExpired(name string)`

## [ActorObject.AddEventLog(category string, message string)](/internal/scripting/actor_func.go)
Adds a line to the users Event Log (`history`)

| Argument | Explanation |
| --- | --- |
| category | A short single word category |
| message | A single line describing the event |
10 changes: 10 additions & 0 deletions _datafiles/guides/building/scripting/SCRIPTING_MOBS.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,3 +203,13 @@ NOTE: You can safely start a new path with `mob.Command('pathto 123')` before re
| mob | [ActorObject](FUNCTIONS_ACTORS.md) |
| room | [RoomObject](FUNCTIONS_ROOMS.md) |
| eventDetails.status | `start`, `waypoint`, or `end` |

`onPlayerDowned()` is called when a player is downed (not killed), and this mob aggro'd on them.
NOTE: If `true` is returned, will ensure this script only runs once for this type of MobId - for example, only one of the two guards in the room.

| Argument | Explanation |
| --- | --- |
| mob | [ActorObject](FUNCTIONS_ACTORS.md) |
| user | [ActorObject](FUNCTIONS_ACTORS.md) |
| room | [RoomObject](FUNCTIONS_ROOMS.md) |

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ itemdropchance: 2
hostile: false
groups:
- frostfang-npc
combatcommands:
- 'callforhelp 7:guard:calls for the guards.'
idlecommands:
- 'say type <ansi fg="command">list</ansi> to see my wares'
- 'say If you''re looking to sell something, I may be interested... as long as it''s not too special or unique'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ itemdropchance: 2
hostile: false
groups:
- frostfang-npc
combatcommands:
- 'callforhelp 7:guard:calls for the guards.'
idlecommands:
- 'say type <ansi fg="command">list</ansi> to see my wares'
- 'say If you''re looking to sell something, I may be interested... as long as it''s not too special or unique'
Expand Down
4 changes: 3 additions & 1 deletion _datafiles/world/default/mobs/frostfang/2-guard.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ itemdropchance: 2
hostile: false
maxwander: 20
groups:
- frostfang-npc
- frostfang-law
combatcommands:
- 'callforhelp 5:puts their fingers to their mouth and whistle loudly.'
activitylevel: 20
character:
name: guard
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ itemdropchance: 2
hostile: false
groups:
- frostfang-npc
combatcommands:
- 'callforhelp 7:guard:calls for the guards.'
activitylevel: 30
maxwander: 5
idlecommands:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ itemdropchance: 2
hostile: false
maxwander: 20
groups:
- frostfang-npc
- frostfang-law
combatcommands:
- 'callforhelp 5:puts their fingers to their mouth and whistle loudly.'
idlecommands:
- 'emote mumbles something about the weather'
- 'wander'
Expand Down
2 changes: 2 additions & 0 deletions _datafiles/world/default/mobs/frostfang/39-elara.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ hostile: false
maxwander: 0
groups:
- frostfang-npc
combatcommands:
- 'callforhelp 7:guard:calls for the guards.'
activitylevel: 20
character:
name: elara
Expand Down
2 changes: 2 additions & 0 deletions _datafiles/world/default/mobs/frostfang/40-rodric.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ idlecommands:
- 'wander'
groups:
- frostfang-npc
combatcommands:
- 'callforhelp 7:guard:calls for the guards.'
activitylevel: 20
character:
name: Rodric
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ hostile: false
maxwander: 0
groups:
- frostfang-npc
combatcommands:
- 'callforhelp 7:guard:calls for the guards.'
idlecommands:
- 'emote checks the edge of their blade.'
- 'emote inspects the training equipment'
Expand Down
2 changes: 2 additions & 0 deletions _datafiles/world/default/mobs/frostfang/5-armorer.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ itemdropchance: 2
hostile: false
groups:
- frostfang-npc
combatcommands:
- 'callforhelp 7:guard:calls for the guards.'
idlecommands:
- 'say type <ansi fg="command">list</ansi> to see my wares'
- 'say If you''re looking to sell something, I may be interested... as long as it''s not too special or unique'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ itemdropchance: 2
hostile: false
groups:
- frostfang-npc
combatcommands:
- 'callforhelp 7:guard:calls for the guards.'
idlecommands:
- 'say type <ansi fg="command">list</ansi> to see what magical objects I have for sale'
activitylevel: 10
Expand Down
2 changes: 2 additions & 0 deletions _datafiles/world/default/mobs/frostfang/6-trainer.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ itemdropchance: 2
hostile: false
groups:
- frostfang-npc
combatcommands:
- 'callforhelp 7:guard:calls for the guards.'
idlecommands:
- 'say I can help you <ansi fg="command">train</ansi> new skills!'
- 'say There are other trainers to be found in the world, with other skills to teach you.'
Expand Down
2 changes: 2 additions & 0 deletions _datafiles/world/default/mobs/frostfang/7-wench.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ itemdropchance: 2
hostile: false
groups:
- frostfang-npc
combatcommands:
- 'callforhelp 7:guard:calls for the guards.'
idlecommands:
- 'say You can <ansi fg="command">sleep</ansi> here for a bit here to refresh.'
- 'say If you''re hungry check the <ansi fg="command">list</ansi> of food for sale.'
Expand Down
2 changes: 2 additions & 0 deletions _datafiles/world/default/mobs/frostfang/8-king.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ itemdropchance: 2
hostile: false
groups:
- frostfang-npc
combatcommands:
- 'callforhelp 7:guard:calls for the guards.'
character:
name: king
description: 'Seated upon his regal throne, the King of Frostfang carries the weight of his kingdom with a quiet dignity. His attire is a rich tapestry of royal blues and silvers, adorned with intricate embroidery that tells the story of his lineage and the battles fought to protect his realm. A heavy, ermine-trimmed cloak drapes over his shoulders, signifying his status and the responsibilities that come with it. His crown, a delicate circlet of silver and sapphires, rests atop his brow, glinting softly in the dim light of the throne room.'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ itemdropchance: 2
hostile: false
maxwander: 2
groups:
- frostfang-npc
- frostfang-law
combatcommands:
- 'callforhelp 5:puts their fingers to their mouth and whistle loudly.'
character:
name: king's guard
description: 'The King''s Guard stands resolute, a formidable perception in the royal throne room. Clad in meticulously maintained armor that gleams under the soft lighting, they exude an air of unwavering loyalty and strength. The guard''s helmet obscures their face, adding an element of mystery and intimidation, while their posture remains erect and vigilant, ready to spring into action at a moment''s notice. A well-polished broadsword hangs at their side, its perception a silent promise to defend the king and the kingdom with their life.'
Expand Down
14 changes: 14 additions & 0 deletions _datafiles/world/default/mobs/frostfang/scripts/2-guard.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,18 @@ function onPath(mob, room, eventDetails) {
}
}

}


function onPlayerDowned(mob, user, room) {

user.SendText(mob.GetCharacterName(true) + " approaches you from behind, striking you with the pommel of their sword.");
user.SendText("The last thing you remember hearing is the jingling of chains as you black out.");

room.SendText(mob.GetCharacterName(true) + " approaches " + user.GetCharacterName(true) + " from behind, striking them with the pommel of their sword.", user.UserId());
room.SendText(mob.GetCharacterName(true) + " places " + user.GetCharacterName(true) + " in chains, and sends them away with a deputy to put them in jail.", user.UserId());

user.MoveRoom(1003);

return true;
}
33 changes: 21 additions & 12 deletions _datafiles/world/default/rooms/frostfang/1003.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ const JAIL_TIME = "1 hour";

function onEnter(user, room) {

user.SetHealth(1);

if ( !room.IsEphemeral() ) {

var newRoomIds = CreateInstancesFromRoomIds( [room.RoomId()] );
Expand All @@ -14,17 +16,23 @@ function onEnter(user, room) {

}

user.TimerSet("jail", JAIL_TIME);

room.SendText("");
room.SendText("<ansi fg=\"red-bold\">********************************************************************************</ansi>");
room.SendText("You hear a loud <ansi fg=\"red-bold\">!!!CLANK!!!</ansi>, and can immediately tell...");
room.SendText("The cell door is LOCKED from the other side!");
room.SendText('You hear someone shout, <ansi fg="saytext-mob">"Maybe an hour in a cell will cool you off!"</ansi>');
room.SendText("<ansi fg=\"red-bold\">********************************************************************************</ansi>");
room.SendText("");

user.Command("look", 1);
if ( !user.TimerExists("jail") ) {

user.AddEventLog(`jail`, `Thrown in jail`);

user.TimerSet("jail", JAIL_TIME);

room.SendText("");
room.SendText("<ansi fg=\"red-bold\">********************************************************************************</ansi>");
room.SendText("You hear a loud <ansi fg=\"red-bold\">!!!CLANK!!!</ansi>, and can immediately tell...");
room.SendText("The cell door is LOCKED from the other side!");
room.SendText('You hear someone shout, <ansi fg="saytext-mob">"Maybe an hour in a cell will cool you off!"</ansi>');
room.SendText("<ansi fg=\"red-bold\">********************************************************************************</ansi>");
room.SendText("");

user.Command("look", 1);

}

return false;
}
Expand All @@ -35,8 +43,9 @@ function onIdle(room) {
var playersInRoom = room.GetPlayers();
for( var i in playersInRoom ) {
if ( playersInRoom[i].TimerExpired("jail") ) {
room.SendText("You hear a loud CLANK, and the cell door is UNLOCKED from the other side.");
room.SendText("You hear a loud <ansi fg=\"red-bold\">!!!KA-LUNK!!!</ansi>, and the cell door is UNLOCKED from the other side.");
room.SetLocked("cell door", false);
playersInRoom[i].AddEventLog(`jail`, `Released from jail`);
}
}
}
Expand Down
7 changes: 6 additions & 1 deletion internal/characters/character.go
Original file line number Diff line number Diff line change
Expand Up @@ -1242,7 +1242,12 @@ func (c *Character) ApplyHealthChange(healthChange int) int {
newHealth := c.Health + healthChange
if newHealth < 0 {
c.CancelBuffsWithFlag(buffs.CancelIfCombat)
if newHealth < -10 {

// If they haven't dropped yet, require a drop before going straight to death.
// Don't allow players to drop under -5 in a single hit.
if newHealth < -5 && oldHealth > 0 {
newHealth = -5
} else if newHealth <= -10 {
newHealth = -10
}
} else if newHealth > c.HealthMax.Value {
Expand Down
7 changes: 7 additions & 0 deletions internal/events/eventtypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,13 @@ type LevelUp struct {

func (l LevelUp) Type() string { return `LevelUp` }

type PlayerDrop struct {
UserId int
RoomId int
}

func (l PlayerDrop) Type() string { return `PlayerDrop` }

type PlayerDeath struct {
UserId int
RoomId int
Expand Down
2 changes: 0 additions & 2 deletions internal/hooks/Message_SendMessages.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ func Message_SendMessage(e events.Event) events.ListenerReturn {
return events.Continue
}

//mudlog.Debug("Message{}", "userId", message.UserId, "roomId", message.RoomId, "length", len(message.Text), "IsCommunication", message.IsCommunication)

if message.UserId > 0 {

if user := users.GetByUserId(message.UserId); user != nil {
Expand Down
11 changes: 4 additions & 7 deletions internal/hooks/NewRound_DoCombat.go
Original file line number Diff line number Diff line change
Expand Up @@ -1075,18 +1075,15 @@ func handleAffected(affectedPlayerIds []int, affectedMobInstanceIds []int) {
if user := users.GetByUserId(userId); user != nil {

if user.Character.Health <= -10 {

user.Command(`suicide`) // suicide drops all money/items and transports to land of the dead.

} else if user.Character.Health < 1 {

user.SendText(`<ansi fg="red">you drop to the ground!</ansi>`)

if room := rooms.LoadRoom(user.Character.RoomId); room != nil {
room.SendText(
fmt.Sprintf(`<ansi fg="username">%s</ansi> <ansi fg="red">drops to the ground!</ansi>`, user.Character.Name),
user.UserId)
}
events.AddToQueue(events.PlayerDrop{UserId: user.UserId, RoomId: user.Character.RoomId})

}

}
}

Expand Down
66 changes: 66 additions & 0 deletions internal/hooks/PlayerDrop_HandlePlayerDrop.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package hooks

import (
"fmt"

"github.com/GoMudEngine/GoMud/internal/events"
"github.com/GoMudEngine/GoMud/internal/mobs"
"github.com/GoMudEngine/GoMud/internal/mudlog"
"github.com/GoMudEngine/GoMud/internal/rooms"
"github.com/GoMudEngine/GoMud/internal/scripting"
"github.com/GoMudEngine/GoMud/internal/users"
)

//
// Some clean up
//

func HandlePlayerDrop(e events.Event) events.ListenerReturn {

evt, typeOk := e.(events.PlayerDrop)
if !typeOk {
mudlog.Error("Event", "Expected Type", "PlayerDrop", "Actual Type", e.Type())
return events.Cancel
}

user := users.GetByUserId(evt.UserId)
if user == nil {
mudlog.Error("HandlePlayerDrop", "error", fmt.Sprintf(`user %d not found`, evt.UserId))
return events.Cancel
}

user.SendText(`<ansi fg="red">you drop to the ground!</ansi>`)

room := rooms.LoadRoom(evt.RoomId)
if room == nil {
return events.Continue
}

room.SendText(
fmt.Sprintf(`<ansi fg="username">%s</ansi> <ansi fg="red">drops to the ground!</ansi>`, user.Character.Name),
user.UserId)

// Loop through all mobs in the room. If any hate the player, try onPlayerDowned()
skipMobIds := map[int]struct{}{}
for _, mobInstanceId := range room.GetMobs() {
mob := mobs.GetInstance(mobInstanceId)
if mob == nil {
continue
}

if _, ok := skipMobIds[int(mob.MobId)]; ok {
continue
}

if !mob.HasAttackedPlayer(user.UserId) {
continue
}

if isUnique, _ := scripting.TryPlayerDownedEvent(mobInstanceId, user.UserId); isUnique {
skipMobIds[int(mob.MobId)] = struct{}{}
}

}

return events.Continue
}
1 change: 1 addition & 0 deletions internal/hooks/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ func RegisterListeners() {
// User Settings change
events.RegisterListener(events.UserSettingChanged{}, ClearSettingCaches)

events.RegisterListener(events.PlayerDrop{}, HandlePlayerDrop)
events.RegisterListener(events.WebClientCommand{}, WebClientCommand_SendWebClientCommand)

events.RegisterListener(events.CharacterCreated{}, BroadcastNewChar)
Expand Down
Loading
Loading