Re: [crossfire] Speech bubbles for NPCs

2020-11-27 Thread Nicolas Weeger
Hello.


Sounds nice :)


Wouldn't it be worth checking the "is_friendly" flag too? I think some monsters 
(raas in particular) have a message defined but will definitely not talk to the 
player :)



Best regards


Nicolas

Le jeudi 26 novembre 2020, 12:39:56 CET Kevin Zheng a écrit :
> Hi there,
> 
> This attached patch, along with the attached archetypes, adds speech
> bubbles to monsters and NPCs.
> 
> Speech bubbles increase discoverability for interesting dialog. In
> Crossfire, there are many NPCs and monsters who have no dialog, and so
> trying to chat up every single NPC is a bit tedious.
> 
> I think a change like this makes the game more fun to play.
> 
> Regards,
> Kevin



signature.asc
Description: This is a digitally signed message part.
___
crossfire mailing list
crossfire@metalforge.org
http://mailman.metalforge.org/mailman/listinfo/crossfire


[crossfire] Speech bubbles for NPCs

2020-11-26 Thread Kevin Zheng

Hi there,

This attached patch, along with the attached archetypes, adds speech 
bubbles to monsters and NPCs.


Speech bubbles increase discoverability for interesting dialog. In 
Crossfire, there are many NPCs and monsters who have no dialog, and so 
trying to chat up every single NPC is a bit tedious.


I think a change like this makes the game more fun to play.

Regards,
Kevin
commit 8b7b28cd058be80ea4326cb53157272d50b8d548
Author: Kevin Zheng 
Date:   Sat Nov 14 10:59:20 2020 -0800

Add build protection

Keep track of the builder's name for player-built tiles. Prevent
destroying or building over other players' tiles.

diff --git a/server/build_map.c b/server/build_map.c
index 1d89cb68..e3228104 100644
--- a/server/build_map.c
+++ b/server/build_map.c
@@ -32,6 +32,15 @@
 #include "sproto.h"
 #include "tod.h"
 
+static bool is_build_owner(object *pl, object *item) {
+const char* owner = object_get_value(item, "build_owner");
+if (owner != NULL) {
+return (strcmp(owner, pl->name) == 0);
+} else {
+return true;
+}
+}
+
 /**
  * Check if objects on a square interfere with building.
  *
@@ -45,11 +54,15 @@
  * @return
  * 0 if new_item can't be built on the spot, 1 if it can be built.
  */
-static int can_build_over(struct mapdef *map, object *new_item, short x, short y) {
+static int can_build_over(object *pl, object *new_item, short x, short y) {
+struct mapdef *map = pl->map;
 FOR_MAP_PREPARE(map, x, y, tmp) {
 object *ob;
 
 ob = HEAD(tmp);
+if (!is_build_owner(pl, ob)) {
+return 0;
+}
 if (strcmp(ob->arch->name, "rune_mark") == 0)
 /* you can always build on marking runes, used for connected building things. */
 continue;
@@ -84,7 +97,7 @@ static int can_build_over(struct mapdef *map, object *new_item, short x, short y
 
 /* If item being built is multi-tile, need to check other parts too. */
 if (new_item->more)
-return can_build_over(map, new_item->more, x+new_item->more->arch->clone.x-new_item->arch->clone.x, y+new_item->more->arch->clone.y-new_item->arch->clone.y);
+return can_build_over(pl, new_item->more, x+new_item->more->arch->clone.x-new_item->arch->clone.x, y+new_item->more->arch->clone.y-new_item->arch->clone.y);
 
 return 1;
 }
@@ -979,6 +992,12 @@ void apply_builder_remove(object *pl, int dir) {
 return;
 }
 
+if (!is_build_owner(pl, item)) {
+draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD,
+  "Can't destroy something you didn't build.");
+return;
+}
+
 /* Now remove object, with special cases (buttons & such) */
 switch (item->type) {
 case WALL:
@@ -1114,7 +1133,7 @@ void apply_map_builder(object *pl, int dir) {
 new_item = object_create_arch(new_arch);
 SET_FLAG(new_item, FLAG_IS_BUILDABLE);
 
-if (!can_build_over(pl->map, new_item, x, y)) {
+if (!can_build_over(pl, new_item, x, y)) {
 draw_ext_info(NDI_UNIQUE, 0, pl, MSG_TYPE_APPLY, MSG_TYPE_APPLY_BUILD,
   "You can't build here.");
 return;
@@ -1144,8 +1163,11 @@ void apply_map_builder(object *pl, int dir) {
 LOG(llevError, "apply_map_builder: invalid material subtype %d\n", material->subtype);
 break;
 }
-if (built)
+if (built) {
 object_decrease_nrof_by_one(material);
+// set owner name
+object_set_value(new_item, "build_owner", pl->name, 1);
+}
 return;
 }
 
Object speechbubble
face speech.111
end
___
crossfire mailing list
crossfire@metalforge.org
http://mailman.metalforge.org/mailman/listinfo/crossfire


Re: [crossfire] Speech bubbles for NPCs

2020-11-26 Thread Kevin Zheng

On 11/26/20 12:39 PM, Kevin Zheng wrote:
This attached patch, along with the attached archetypes, adds speech 
bubbles to monsters and NPCs.


I attached the wrong patch. The right one is attached here.
commit 300ed7b84bca652912e2f6b557ab1556383263fc
Author: Kevin Zheng 
Date:   Sat Nov 7 12:45:58 2020 -0800

Add speech bubbles

diff --git a/socket/request.c b/socket/request.c
index aaf82548..c1759c70 100644
--- a/socket/request.c
+++ b/socket/request.c
@@ -1210,6 +1210,18 @@ static int check_probe(int ax, int ay, const object *ob, SockList *sl, socket_st
 return got_one;
 }
 
+static int annotate_ob(int ax, int ay, const object *ob, SockList *sl, socket_struct *ns, int *has_obj, int *alive_layer) {
+int got_one = check_probe(ax, ay, ob, sl, ns, has_obj, alive_layer);
+if (QUERY_FLAG(ob, FLAG_ALIVE) && ob->msg != NULL && ob->type != PLAYER) {
+archetype *dummy = try_find_archetype("speechbubble");
+if (dummy != NULL) {
+got_one += map2_add_ob(ax, ay, MAP_LAYER_FLY2, >clone, sl, ns, has_obj, 0);
+(*alive_layer) = MAP_LAYER_FLY2;
+}
+}
+return got_one;
+}
+
 /*
  * This function is used to check a space (ax, ay) whose only
  * data we may care about are any heads. Basically, this
@@ -1409,7 +1421,7 @@ static void draw_client_map2(object *pl) {
 
 /* if we added the face, or it is a monster's head, check probe spell */
 if (got_one != old_got || (ob->head == NULL && ob->more))
-got_one += check_probe(ax, ay, ob, , >socket, _obj, _layer);
+got_one += annotate_ob(ax, ay, ob, , >socket, _obj, _layer);
 
 /* If we are just storing away the head
  * for future use, then effectively this
@@ -1420,7 +1432,7 @@ static void draw_client_map2(object *pl) {
 del_one += map2_delete_layer(ax, ay, layer, , >socket);
 } else if (ob->head == NULL) {
 /* for single-part items */
-got_one += check_probe(ax, ay, ob, , >socket, _obj, _layer);
+got_one += annotate_ob(ax, ay, ob, , >socket, _obj, _layer);
 }
 } else {
 if (layer != alive_layer)
___
crossfire mailing list
crossfire@metalforge.org
http://mailman.metalforge.org/mailman/listinfo/crossfire