Angband.oook.cz
Angband.oook.cz
AboutVariantsLadderForumCompetitionComicScreenshotsFunniesLinks

Go Back   Angband Forums > Angband > Development

Reply
 
Thread Tools Display Modes
Old August 29, 2021, 17:01   #171
Pete Mack
Prophet
 
Join Date: Apr 2007
Location: Seattle, WA
Posts: 6,589
Donated: $40
Pete Mack is on a distinguished road
But if there is an array of curses for each object, surely they all share the same obj pointer?
Pete Mack is online now   Reply With Quote
Old August 29, 2021, 23:20   #172
Nick
Vanilla maintainer
 
Nick's Avatar
 
Join Date: Apr 2007
Location: Canberra, Australia
Age: 56
Posts: 9,167
Donated: $60
Nick will become famous soon enoughNick will become famous soon enough
Quote:
Originally Posted by Pete Mack View Post
But if there is an array of curses for each object, surely they all share the same obj pointer?
Each object has a curses array where each entry is a struct of two integers, power and timeout (for timed effects); the object has the curse if the power is non-zero. The actual curses are stored in the global curses[], which is of struct curse - that struct contains a struct object for the actual curse effects, plus name, description, etc.

The reason it's like this is that when I was designing the curse struct, I found myself mimicking the object struct, which makes sense because curses just change the behaviour of an object.
__________________
One for the Dark Lord on his dark throne
In the Land of Mordor where the Shadows lie.
Nick is offline   Reply With Quote
Old September 3, 2021, 05:08   #173
will_asher
DaJAngband Maintainer
 
will_asher's Avatar
 
Join Date: Apr 2007
Location: San Antonio, TX
Posts: 1,123
Donated: $10
will_asher is on a distinguished road
Doing grenades was easy was DaJAngband, but now the way the code has changed, a lot of things are harder to customize for someone like me who's not fluent in C.

Here's what I'm trying to do:
(in player_attack.c)
Code:
 */
static struct attack_result make_ranged_throw(struct player *p,
	struct object *obj, struct loc grid)
{
	char *hit_verb = mem_alloc(20 * sizeof(char));
	struct attack_result result = {false, 0, 0, hit_verb};
	struct monster *mon = square_monster(cave, grid);
	int b = 0, s = 0;

	my_strcpy(hit_verb, "hits", 20);

	/* If we missed then we're done */
	if (!test_hit(chance_of_missile_hit(p, obj, NULL, mon), mon->race->ac))
		return result;

	result.success = true;

	/* EXPLODEing (with grenades) works separately */
	if (of_has(obj->flags, OF_EXPLODE)) {
		result.dmg = ranged_damage(p, mon, obj, NULL, 0, 0);
		/* Use "STRIKE" effect but use "other" param to bypass asking for target and requirement of being in view of the PC. */
		effect_simple(EF_STRIKE, source_player(), format("%d", result.dmg), 0, 2, 9, grid->y, grid->x,
			NULL);
		return result;
	}
...<rest of function>
using "grid->y" and "grid->x" gives me errors. But I can't pass a grid to effect_simple, I need x and y coordinates. How do I access x and y without causing errors here?
Also, the way the code does brands and slays now, I don't know how to get the brand type from the grenade to know what subtype to use with effect_simple here.
__________________
Will_Asher
aka LibraryAdventurer

My old variant DaJAngband:
http://sites.google.com/site/dajangbandwebsite/home (defunct and so old it's forked from Angband 3.1.0 -I think- but it's probably playable...)
will_asher is offline   Reply With Quote
Old September 3, 2021, 08:42   #174
AnonymousHero
Veteran
 
AnonymousHero's Avatar
 
Join Date: Jun 2007
Posts: 1,383
AnonymousHero is on a distinguished road
A couple of notes about the code: (I've marked inline with an ascii arrow.)

Quote:
Originally Posted by will_asher View Post
Code:
/* Modifiers to object weight */
int object_weight(const struct object* obj)
{
           <--- probably a good idea to assert that obj != NULL here.
	int weight = obj->weight;  <-- This assumes obj is not null, or Undefined Behavior ensues
	int index = 0;

	/* Check for curses */
	struct curse_data* curse = obj ? obj->curses : NULL; 
        ^-- You don't need to test for "obj" here, it cannot be null by definition because
              you've dereferenced it when initializing "weight" above


	/* (copied from calc_bonuses()) */
	while (obj) {
		/* Curses may affect weight (index zero is original object) */
		if ((obj->weight) && (index)) weight += obj->weight;  
                ^-- You don't need to have "obj->weight" in the condition here, adding 0 doesn't change anything, so you don't need to check
                EDIT: You can also just declare "index = 1" rather than "index = 0" at the start and drop the conditional altogether
                        If index starts at 1 you can just add the weight regardless.


		/* next curse if any */
		if (curse) {
			index++;
			obj = NULL;
			while (index < z_info->curse_max) {
				if (curse[index].power) {
					obj = curses[index].obj;
					break;
				}
				else { 
                                    ^-- No need for else, just use "index++" without an else around it. If the
                                          previous condition is true, you'll break out of the loop anyway.
					index++;
				}
			}
		}
		else {
			obj = NULL;
		}
	}

	return weight;
}
EDIT: Added a couple of extra notes, and hopefully formatting is less crazy now

Last edited by AnonymousHero; September 3, 2021 at 17:57.
AnonymousHero is offline   Reply With Quote
Old September 3, 2021, 21:21   #175
Julian
Apprentice
 
Join Date: Apr 2021
Posts: 87
Julian is on a distinguished road
Quote:
Originally Posted by AnonymousHero View Post
A couple of notes about the code: (I've marked inline with an ascii arrow.)

Code:
while (obj) {
		/* Curses may affect weight (index zero is original object) */
		if ((obj->weight) && (index)) weight += obj->weight;  
                ^-- You don't need to have "obj->weight" in the condition here, adding 0 doesn't change anything, so you don't need to check
                EDIT: You can also just declare "index = 1" rather than "index = 0" at the start and drop the conditional altogether
                        If index starts at 1 you can just add the weight regardless.


		/* next curse if any */
		if (curse) {
			index++;
			obj = NULL;
			while (index < z_info->curse_max) {
				if (curse[index].power) {
					obj = curses[index].obj;
					break;
				}
				else { 
                                    ^-- No need for else, just use "index++" without an else around it. If the
                                          previous condition is true, you'll break out of the loop anyway.
					index++;
				}
			}
		}
		else {
			obj = NULL;
		}
	}
EDIT: Added a couple of extra notes, and hopefully formatting is less crazy now
This entire loop structure is kind of weird. The whole process is just “look up object’s weight, and if it has curses, loop through them and add their weights”, isn’t it? That’s mostly an if and either a for or a while loop.
Julian is offline   Reply With Quote
Old September 4, 2021, 02:15   #176
Pete Mack
Prophet
 
Join Date: Apr 2007
Location: Seattle, WA
Posts: 6,589
Donated: $40
Pete Mack is on a distinguished road
That is what i thought. It's way too complex for what you'd expect to be a simple iterator.
Pete Mack is online now   Reply With Quote
Old September 4, 2021, 02:49   #177
Nick
Vanilla maintainer
 
Nick's Avatar
 
Join Date: Apr 2007
Location: Canberra, Australia
Age: 56
Posts: 9,167
Donated: $60
Nick will become famous soon enoughNick will become famous soon enough
Quote:
Originally Posted by will_asher View Post
using "grid->y" and "grid->x" gives me errors. But I can't pass a grid to effect_simple, I need x and y coordinates. How do I access x and y without causing errors here?
The "->" is if you have a pointer to the struct (so if grid was a struct loc *), if it's just the struct you need a ".". So grid.y and grid.x should work.

Quote:
Originally Posted by will_asher View Post
Also, the way the code does brands and slays now, I don't know how to get the brand type from the grenade to know what subtype to use with effect_simple here.
The EXPLODE flag just multiplies raw damage by 3. I think here you get to decide what subtype you want to use - the obvious possibilities are MISSILE for just raw damage, or if you want it to feel more like a physical explosion FIRE or SHARDS (or both one after the other).
__________________
One for the Dark Lord on his dark throne
In the Land of Mordor where the Shadows lie.
Nick is offline   Reply With Quote
Old September 4, 2021, 05:56   #178
will_asher
DaJAngband Maintainer
 
will_asher's Avatar
 
Join Date: Apr 2007
Location: San Antonio, TX
Posts: 1,123
Donated: $10
will_asher is on a distinguished road
Quote:
Originally Posted by Nick View Post
The EXPLODE flag just multiplies raw damage by 3. I think here you get to decide what subtype you want to use - the obvious possibilities are MISSILE for just raw damage, or if you want it to feel more like a physical explosion FIRE or SHARDS (or both one after the other).
Ordinarily, it'll be fire and shards, but grenades can get brand egos. I just don't know how to make the brand egos work with them.
(EDIT: I don't want the STRIKE effect damage to depend on damage to the particular monster it hits because other nearby monsters may have different resistances.)
__________________
Will_Asher
aka LibraryAdventurer

My old variant DaJAngband:
http://sites.google.com/site/dajangbandwebsite/home (defunct and so old it's forked from Angband 3.1.0 -I think- but it's probably playable...)
will_asher is offline   Reply With Quote
Old September 4, 2021, 17:57   #179
backwardsEric
Adept
 
Join Date: Aug 2019
Posts: 217
backwardsEric is on a distinguished road
Quote:
Originally Posted by will_asher View Post
Ordinarily, it'll be fire and shards, but grenades can get brand egos. I just don't know how to make the brand egos work with them.
(EDIT: I don't want the STRIKE effect damage to depend on damage to the particular monster it hits because other nearby monsters may have different resistances.)
Can they have more than one brand? If only one is possible, then you could look through the brand array to see what ,if anything, is set, look up the related modifier and element for the brand, and use those when you invoke the effect to handle the grenade's explosion. If multiple brands are possible, I suspect you'd either have to write a custom effect handler (loop over the monsters in the range of the effect; for each, determine which brand does the most damage) or split the total base damage among the brands that are present and call one of the standard effect handlers for each of those brands.
backwardsEric is offline   Reply With Quote
Old September 5, 2021, 06:25   #180
will_asher
DaJAngband Maintainer
 
will_asher's Avatar
 
Join Date: Apr 2007
Location: San Antonio, TX
Posts: 1,123
Donated: $10
will_asher is on a distinguished road
Lightbulb

Quote:
Originally Posted by backwardsEric View Post
Can they have more than one brand? If only one is possible, then you could look through the brand array to see what ,if anything, is set, look up the related modifier and element for the brand, and use those when you invoke the effect to handle the grenade's explosion.
They can only get one brand.
So this is what I have so far:

in make_ranged_throw()
Code:
	/* EXPLODEing (with grenades) works separately (half FIRE and half SHARD) (but they have a chance to dud and not explode) */
	if ((of_has(obj->flags, OF_EXPLODE)) && (randint0(100) < 96 + player->p_luck)) {
		int elem = ELEM_FIRE;
		result.dmg = ranged_damage(p, mon, obj, NULL, 0, 0); /* (doubled) */
		if (obj->brands) {
			elem = grenade_brand(obj);
			/* It's already being doubled, so this makes it x3 */
			result.dmg = (result.dmg * 3 + 1) / 2;
		}
		/* Use "STRIKE" effect with "other" param to bypass asking for target and requirement of being in view of the PC. */
		effect_simple(EF_STRIKE, source_player(), format("%d", result.dmg), ELEM_SHARD, 2, 9, grid.y, grid.x, NULL);
		effect_simple(EF_STRIKE, source_player(), format("%d", result.dmg), elem, 2, 9, grid.y, grid.x, NULL); (EDIT: fixed)
		return result;
	}
with this
Code:
<EDIT: see below. snipped incomplete version>
How do I identify the brand so I know what this needs to return?
EDIT: okay, here's what I did:
Code:
/* Get a brand from a grenade */
int grenade_brand(struct object* obj)
{
	int i;
	/* Brands (copied from improve_attack_modifier()) */
	for (i = 1; i < z_info->brand_max; i++) {
		struct brand* b = &brands[i];

		if (!obj->brands[i]) continue;
		if (b->resist_flag == RF_IM_ACID) return ELEM_ACID;
		if (b->resist_flag == RF_IM_COLD) return ELEM_COLD;
		if (b->resist_flag == RF_IM_FIRE) return ELEM_FIRE;
		if (b->resist_flag == RF_IM_ELEC) return ELEM_ELEC;
		if (b->resist_flag == RF_IM_POIS) return ELEM_POIS;
	}
	/* shouldn't get here because this is only called if there's a brand on the grenade */
	return ELEM_FIRE;
}
EDIT: The "other" parameter doesn't seem to be getting passed to the STRIKE function because it's still asking for a direction (3 times...)
__________________
Will_Asher
aka LibraryAdventurer

My old variant DaJAngband:
http://sites.google.com/site/dajangbandwebsite/home (defunct and so old it's forked from Angband 3.1.0 -I think- but it's probably playable...)

Last edited by will_asher; September 7, 2021 at 00:32.
will_asher is offline   Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
can we make identify more common ? Sky Vanilla 16 September 10, 2017 11:20
Make Artistry automatic bagori nd Sil 4 September 26, 2016 19:22
How many variant developers/maintainers have beaten their own variant? Delver Variants 12 June 5, 2009 10:08
Variant writing.. quickstart guide? Also, Hengband variant suggestions? dzhang Variants 34 April 1, 2009 01:45
Trying to make my own variant bpleshek Variants 8 September 15, 2008 21:42


All times are GMT +1. The time now is 20:03.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2021, vBulletin Solutions Inc.