Exemple #1
0
/**
 * All but object "save_item" are removed from the container list. Note
 * we have to becareful to remove the inventories of objects in the
 * cauldron inventory (ex icecube has stuff in it).
 * @param first_ob Container from which to remove.
 * @param save_item What item not to remove. Can be NULL. */
static void remove_contents(object *first_ob, object *save_item)
{
	object *next, *tmp = first_ob;

	while (tmp)
	{
		next = tmp->below;

		if (tmp == save_item)
		{
			if (!(tmp = next))
			{
				break;
			}
			else
			{
				next = next->below;
			}
		}

		if (tmp->inv)
		{
			remove_contents(tmp->inv, NULL);
		}

		remove_ob(tmp);
		tmp = next;
	}
}
Exemple #2
0
/**
 * Essentially a wrapper for make_item_from_recipe() and
 * insert_ob_in_ob(). If the caster has some alchemy skill, then they
 * might gain some exp from (successful) fabrication of the product.
 * If nbatches==-1, don't give exp for this creation (random generation/
 * failed recipe)
 * @param caster Who is trying to do alchemy.
 * @param cauldron Container used for alchemy.
 * @param rp Recipe attempted.
 * @param nbatches If -1, don't give exp for this creation (random
 * generation/failed recipe)
 * @return Generated item, can be NULL if contents were destroyed. */
static object *attempt_recipe(object *caster, object *cauldron, int ability, recipe *rp, int nbatches)
{
	object *item = NULL;
	/* This should be passed to this function, not too effiecent cpu use this way */
	int batches = abs(nbatches);

	/* Code required for this recipe, search the caster */
	if (rp->keycode)
	{
		object *tmp;

		for (tmp = caster->inv; tmp != NULL; tmp = tmp->below)
		{
			if (tmp->type == FORCE && tmp->slaying && !strcmp(rp->keycode, tmp->slaying))
			{
				break;
			}
		}

		/* Failure - no code found */
		if (tmp == NULL)
		{
			new_draw_info(NDI_UNIQUE, caster, "You know the ingredients, but not the technique. Go learn how to do this recipe.");
			return NULL;
		}
	}

#ifdef EXTREME_ALCHEMY_DEBUG
	LOG(llevDebug, "DEBUG: attempt_recipe(): got %d nbatches\n", nbatches);
	LOG(llevDebug, "DEBUG: attempt_recipe(): using recipe %s\n", rp->title ? rp->title : "unknown");
#endif

	if ((item = make_item_from_recipe(cauldron, rp)) != NULL)
	{
		remove_contents(cauldron->inv, item);
		/* adj lvl, nrof on caster level */
		adjust_product(item, ability, rp->yield ? (rp->yield * batches) : batches);

		if (!item->env && (item = insert_ob_in_ob(item, cauldron)) == NULL)
		{
			new_draw_info(NDI_UNIQUE, caster, "Nothing happened.");
		}
		else
		{
			new_draw_info_format(NDI_UNIQUE, caster, "The %s %s.", cauldron->name, cauldron_sound());
		}
	}

	return item;
}
Exemple #3
0
/**
 * Ouch. We didn't get the formula we wanted. This function simulates the
 * backfire effects -- worse effects as the level increases. If
 * SPELL_FAILURE_EFFECTS is defined some really evil things can happen to
 * the would be alchemist. This table probably needs some adjustments for
 * playbalance.
 * @param op Who tried to do alchemy.
 * @param cauldron Container that was used.
 * @param rp Rrecipe that failed.
 * @param danger Danger value, the higher the more evil the effect. */
static void alchemy_failure_effect(object *op, object *cauldron, recipe *rp, int danger)
{
	int level = 0;

	if (!op || !cauldron)
	{
		return;
	}

	if (danger > 1)
	{
		level = rndm(1, danger);
	}

#ifdef ALCHEMY_DEBUG
	LOG(llevDebug, "DEBUG: Alchemy_failure_effect(): using level=%d\n", level);
#endif

	/* possible outcomes based on level */

	/* Ingredients destroyed, and possibly create slag. */
	if (level < 25)
	{
		object *item = NULL;

		/* Slag created */
		if (rndm(0, 2))
		{
			object *tmp = cauldron->inv;
			int weight = 0;
			uint16 material = M_STONE;

			/* Slag has coadded ingredient properties */
			while (tmp)
			{
				weight += tmp->weight;

				if (!(material & tmp->material))
				{
					material = material | tmp->material;
				}

				tmp = tmp->below;
			}

			tmp = get_archetype("rock");
			tmp->weight = weight;
			tmp->value = 0;
			tmp->material = material;
			FREE_AND_COPY_HASH(tmp->name, "slag");
			item = insert_ob_in_ob(tmp, cauldron);
			CLEAR_FLAG(tmp, FLAG_CAN_ROLL);
			CLEAR_FLAG(tmp, FLAG_NO_PICK);
			CLEAR_FLAG(tmp, FLAG_NO_PASS);
		}

		remove_contents(cauldron->inv, item);
		new_draw_info_format(NDI_UNIQUE, op, "The %s %s.", cauldron->name, cauldron_sound());
		return;
	}
	/* Make tained item. */
	else if (level < 40)
	{
		object *tmp = NULL;

		if (!rp)
		{
			if ((rp = get_random_recipe(NULL)) == NULL)
			{
				return;
			}
		}

		if ((tmp = attempt_recipe(op, cauldron, 1, rp, -1)))
		{
			/* Curse it */
			if (!QUERY_FLAG(tmp, FLAG_CURSED))
			{
				SET_FLAG(tmp, FLAG_CURSED);
			}

			/* Special stuff for consumables */
			if (tmp->type == FOOD)
			{
				tmp->stats.sp = 0;

				/* Poisonous */
				if (rndm(0, 1))
				{
					tmp->type = FOOD;
					tmp->stats.hp = rndm(0, 149);
				}
			}

			/* Unsaleable item */
			tmp->value = 0;

			/* Change stats downward */
			do
			{
				change_attr_value(&tmp->stats, rndm(0, 6), (signed char) (-1 * (rndm(1, 3))));
			}
			while (rndm(0, 2));
		}

		return;
	}

	/* Make random recipe. */
	if (level == 40)
	{
		recipelist *fl;
		int numb = numb_ob_inside(cauldron);

		/* Take a lower recipe list */
		fl = get_formulalist(numb - 1);

		if (fl && (rp = get_random_recipe(fl)))
		{
			/* Even though random, don't grant user any EXP for it */
			(void) attempt_recipe(op, cauldron, 1, rp, -1);
		}
		else
		{
			alchemy_failure_effect(op, cauldron, rp, level - 1);
		}

		return;
	}
	/* Infuriate NPCs */
	else if (level < 45)
	{
		alchemy_failure_effect(op, cauldron, rp, level - 5);
		return;
	}
	/* Minor explosion/fireball */
	else if (level < 50)
	{
		object *tmp;

		remove_contents(cauldron->inv, NULL);

		switch (rndm(0, 2))
		{
			case 0:
				tmp = get_archetype("bomb");
				tmp->stats.dam = rndm(1, level);
				tmp->stats.hp = rndm(1, level);
				new_draw_info_format(NDI_UNIQUE, op, "The %s creates a bomb!", cauldron->name);
				break;

			default:
				tmp = get_archetype("fireball");
				tmp->stats.dam = rndm(1, level) / 5 + 1;
				tmp->stats.hp = rndm(1, level) / 10 + 2;
				new_draw_info_format(NDI_UNIQUE, op, "The %s erupts in flame!", cauldron->name);
				break;
		}

		tmp->x = cauldron->x, tmp->y = cauldron->y;
		insert_ob_in_map(tmp, op->map, NULL, 0);
		return;
	}
	/* Create monster */
	else if (level < 60)
	{
		new_draw_info_format(NDI_UNIQUE, op, "The %s %s.", cauldron->name, cauldron_sound());
		remove_contents(cauldron->inv, NULL);
		return;
	}
	/* Major fire */
	else if (level < 80)
	{
		remove_contents(cauldron->inv, NULL);
#if 0
		fire_arch_from_position(cauldron, cauldron, cauldron->x, cauldron->y, 0, spellarch[SP_L_FIREBALL], SP_L_FIREBALL, NULL);
#endif
		new_draw_info_format(NDI_UNIQUE, op, "The %s erupts in flame!", cauldron->name);
		return;
	}
	/* Whammy the cauldron */
	else if (level < 100)
	{
		if (!QUERY_FLAG(cauldron, FLAG_CURSED))
		{
			SET_FLAG(cauldron, FLAG_CURSED);
		}
		else
		{
			cauldron->magic--;
		}

		cauldron->magic -= rndm(0, 4);

		if (rndm(0, 1))
		{
			remove_contents(cauldron->inv, NULL);
			new_draw_info_format(NDI_UNIQUE, op, "Your %s turns darker then makes a gulping sound!", cauldron->name);
		}
		else
		{
			new_draw_info_format(NDI_UNIQUE, op, "Your %s becomes darker.", cauldron->name);
		}

		return;
	}
	/* Summon evil monsters */
	else if (level < 110)
	{
		object *tmp = get_random_mon();

		remove_contents(cauldron->inv, NULL);

		if (!tmp)
		{
			alchemy_failure_effect(op, cauldron, rp, level);
		}

		return;
	}
	/* Combo effect */
	else if (level < 150)
	{
		int roll = rndm(1, 3);

		while (roll)
		{
			alchemy_failure_effect(op, cauldron, rp, level - 39);
			roll--;
		}

		return;
	}
	/* Create random artifact */
	else if (level == 151)
	{
		object *tmp;

		/* this is meant to be better than prior possiblity,
		 * in this one, we allow *any* valid alchemy artifact
		 * to be made (rather than only those on the given
		 * formulalist) */
		if (!rp)
		{
			rp = get_random_recipe((recipelist *) NULL);
		}

		if (rp && (tmp = get_archetype(rp->arch_name)))
		{
			generate_artifact(tmp, rndm(1, op->level / 2 + 1) + 1, 0, 99);

			if ((tmp = insert_ob_in_ob(tmp, cauldron)))
			{
				remove_contents(cauldron->inv, tmp);
				new_draw_info_format(NDI_UNIQUE, op, "The %s %s.", cauldron->name, cauldron_sound());
			}
		}

		return;
	}
	/* Mana storm -- watch out! */
	else if (level < 200)
	{
		new_draw_info(NDI_UNIQUE, op, "You unwisely release potent forces!");
		remove_contents(cauldron->inv, NULL);
		cast_magic_storm(op, get_archetype("loose_magic"), level);
		return;
	}
}
void Project::save( bool onlyProjectFile )
{
    bool anythingModified = FALSE;

    //  save sources and forms
    if ( !onlyProjectFile ) {

	saveConnections();

	for ( SourceFile *sf = sourcefiles.first(); sf; sf = sourcefiles.next() ) {
	    anythingModified = anythingModified || sf->isModified();
	    if ( !sf->save() )
		return;
	}

	for ( FormFile *ff = formfiles.first(); ff; ff = formfiles.next() ) {
	    anythingModified = anythingModified || ff->isModified();
	    if ( !ff->save() )
		return;
	}
    }

    if ( isDummy() || filename.isEmpty() )
	return;

    if ( !modified ) {
	if ( singleProjectMode() ) {
	    LanguageInterface *iface = MetaDataBase::languageInterface( language() );
	    if ( iface && iface->supports( LanguageInterface::CompressProject ) )
		iface->compressProject( makeAbsolute( filename ), singleProFileName, anythingModified );
	}
 	return;
    }

    QFile f( filename );
    QString original = "";

    // read the existing file
    bool hasPreviousContents = FALSE;
    if ( f.open( IO_ReadOnly ) ) {
	QTextStream ts( &f );
	original = ts.read();
	f.close();
        hasPreviousContents = TRUE;
	remove_contents( original, "{SOURCES+=" ); // ### compatibility with early 3.0 betas
	remove_contents( original, "DBFILE" );
	remove_contents( original, "LANGUAGE" );
	remove_contents( original, "TEMPLATE" );
	removePlatformSettings( original, "CONFIG" );
	removePlatformSettings( original, "DEFINES" );
	removePlatformSettings( original, "LIBS" );
	removePlatformSettings( original, "INCLUDEPATH" );
	removePlatformSettings( original, "SOURCES" );
	removePlatformSettings( original, "HEADERS" );
	remove_multiline_contents( original, "FORMS" );
	remove_multiline_contents( original, "INTERFACES" ); // compatibility
	remove_multiline_contents( original, "IMAGES" );
	for ( QStringList::Iterator it = csList.begin(); it != csList.end(); ++it )
	    remove_contents( original, *it );
    }

    if (!original.isEmpty()) {
	// Removes any new lines at the beginning of the file
	while (original.startsWith("\n"))
	    original.remove(0, 1);
    }

    // the contents of the saved file
    QString contents;

    // template
    contents += "TEMPLATE\t= " + templ + "\n";

    // language
    contents += "LANGUAGE\t= " + lang + "\n";
    contents += "\n";

    // config
    writePlatformSettings( contents, "CONFIG", cfg );
    LanguageInterface *iface = MetaDataBase::languageInterface( lang );
    if ( iface ) {
	QStringList sourceKeys;
	iface->sourceProjectKeys( sourceKeys );
	for ( QStringList::Iterator spit = sourceKeys.begin(); spit != sourceKeys.end(); ++spit )
	    remove_multiline_contents( contents, *spit );
    }

    // libs, defines, includes
    writePlatformSettings( contents, "LIBS", lbs );
    writePlatformSettings( contents, "DEFINES", defs );
    writePlatformSettings( contents, "INCLUDEPATH", inclPath );
    writePlatformSettings( contents, "SOURCES", sources );
    writePlatformSettings( contents, "HEADERS", headers );

    // unix
    if ( !hasPreviousContents ) {
 	contents +=
 	    "unix|os2 {\n"
 	    "  UI_DIR = .ui\n"
 	    "  MOC_DIR = .moc\n"
 	    "  OBJECTS_DIR = .obj\n"
 	    "}\n\n";
    }

    // sources
    if ( !sourcefiles.isEmpty() && iface ) {
	QMap<QString, QStringList> sourceToKey;
	for ( SourceFile *f = sourcefiles.first(); f; f = sourcefiles.next() ) {
	    QString key = iface->projectKeyForExtension( QFileInfo( f->fileName() ).extension() );
	    QStringList lst = sourceToKey[ key ];
	    lst << makeRelative( f->fileName() );
	    sourceToKey.replace( key, lst );
	}

	for ( QMap<QString, QStringList>::Iterator skit = sourceToKey.begin();
	      skit != sourceToKey.end(); ++skit ) {
	    QString part = skit.key() + "\t+= ";
	    QStringList lst = *skit;
	    for ( QStringList::Iterator sit = lst.begin(); sit != lst.end(); ++sit ) {
		part += *sit;
		part += ++sit != lst.end() ? " \\\n\t" : "";
		--sit;
	    }
	    part += "\n\n";
	    contents += part;
	}
    }

    // forms and interfaces
    if ( !formfiles.isEmpty() ) {
	contents += "FORMS\t= ";
	for ( QPtrListIterator<FormFile> fit = formfiles; fit.current(); ++fit ) {
	    contents += fit.current()->fileName() +
		 (fit != formfiles.last() ? " \\\n\t" : "");
	}
	contents += "\n\n";
    }

    // images
     if ( !pixCollection->isEmpty() ) {
	contents += "IMAGES\t= ";
	QValueList<PixmapCollection::Pixmap> pixmaps = pixCollection->pixmaps();
	for ( QValueList<PixmapCollection::Pixmap>::Iterator it = pixmaps.begin();
	      it != pixmaps.end(); ++it ) {
		  contents += makeRelative( (*it).absname );
		  contents += ++it != pixmaps.end() ? " \\\n\t" : "";
		  --it;
	}
	contents += "\n\n";
    }

    // database
    if ( !dbFile.isEmpty() )
	contents += "DBFILE\t= " + dbFile + "\n";

    // custom settings
    for ( QStringList::Iterator it = csList.begin(); it != csList.end(); ++it ) {
	QString val = *customSettings.find( *it );
	if ( !val.isEmpty() )
	    contents += *it + "\t= " + val + "\n";
    }

    if ( !f.open( IO_WriteOnly | IO_Translate ) ) {
	QMessageBox::warning( messageBoxParent(),
			      "Save Project Failed", "Couldn't write project file " + filename );
	return;
    }

    QTextStream os( &f );
    os << contents;
    if (hasPreviousContents)
        os << original;

    f.close();

    setModified( FALSE );

    if ( singleProjectMode() ) {
	LanguageInterface *iface = MetaDataBase::languageInterface( language() );
	if ( iface && iface->supports( LanguageInterface::CompressProject ) )
	    iface->compressProject( makeAbsolute( filename ), singleProFileName, TRUE );
    }
}