Hi there! You are currently browsing as a guest. Why not create an account? Then you get less ads, can thank creators, post feedback, keep a list of your favourites, and more!
Lab Assistant
Original Poster
#1 Old 20th Jul 2012 at 4:25 AM Last edited by SuicidalSpiders : 20th Jul 2012 at 6:39 AM.
Default Help creating a mod to charge for taxis...
I'm trying to create a mod that makes it so that taking a taxi isn't free. I looked in the xml file for taxis and saw that there wasn't a cost string in there, so I stole the one from the pizza service...it didn't work... Any suggestions? Any help is appreciated.

Edit...Ok, I've gotten some help from someone and they had me download ILSpy...I poked around, but couldn't find anything useful...I think this is just way over my head...Any modders interested in tackling this?
Advertisement
Lab Assistant
#2 Old 20th Jul 2012 at 7:21 AM
You might interested in "Sims3.Gameplay.Objects.Vehicles.Taxi" or something similar....
And you'll find some interaction related to sims take taxi or other transport, like that...

I'm not sure, probably you'll need to replace those traffic interaction,
and have sims' family fund taken away when sims leaving the taxi.

Work hard, code hard.
Hard code, hard work.
Lab Assistant
Original Poster
#3 Old 20th Jul 2012 at 9:58 PM
But, how would I do that?
Eminence Grise
#4 Old 21st Jul 2012 at 5:04 AM
Would be a scripting mod Writing your own code... Not something where you can just alter values. You can't add new game behavior through XML.

If you want to dive in, I'd start with the scripting tutorials under General Modding; that should give you enough of an idea of what questions to ask to go further.

Otherwise, you can try the WCIF forum under Help to see if somebody's made it. No requests here
Lab Assistant
Original Poster
#5 Old 21st Jul 2012 at 6:57 AM
Oh, ok...thanks Srikandi...I'll take a look at those.
Field Researcher
#6 Old 27th Nov 2013 at 8:19 AM Last edited by Sleepy-Genius : 27th Nov 2013 at 2:27 PM.
I am going to make my attempt to tackle this. I'd like to have this mod in game as well.
Hopefully those Java classes I have taken come into hand.

As of now, I am stuck again.



I want to do a speed = time * distance type formula, then give that result to int fee.
Screenshots
Ms. Byte (Deceased)
#7 Old 27th Nov 2013 at 9:13 PM
Quote: Originally posted by Sleepy-Genius
I am going to make my attempt to tackle this. I'd like to have this mod in game as well.
Hopefully those Java classes I have taken come into hand.

As of now, I am stuck again.



I want to do a speed = time * distance type formula, then give that result to int fee.


I see two problems:

1) You can't (or at least shouldn't) assign a value to a parameter unless it's an 'out' parameter. (I assume you're writing in C#.) (http://msdn.microsoft.com/en-us/lib...4(v=vs.71).aspx) If you're calculating fee you don't need it passed in to the method.

2) TimeUnit.Seconds is an enumerator for the type of time units in the game, specifically seconds. I think what you're trying to do here is multiply the fee times a number of seconds - maybe the amount of time the taxi will charge for? You need a number of seconds, not the definition of a second within the game.

Please do not PM me with mod, tutorial, or general modding questions or problems; post them in the thread for the mod or tutorial or post them in the appropriate forum.

Visit my blogs for other Sims content:
Online Sims - general mods for Sims 3
Offline Sims - adult mods for Sims 3 and Sims 4
Field Researcher
#8 Old 29th Nov 2013 at 4:43 AM Last edited by Sleepy-Genius : 16th Dec 2013 at 8:38 AM.
I've been looking for the code that controls the time span for the actual seconds (how long the taxi took to get to point a from point b), but I haven't yet. I thought that was it. :/
I'm still searching (in reflector and internet) for it. I'm sure it will turn out to be right in my face.

Edit 9:23pm
I think this is the correct way to use time.
Code:
public static int sOneSecond = ((int)SimClock.ConvertToTicks(1f, TimeUnit.Seconds));

I'm going to test to see if this works.

Edit: 12:59am
So of course it didn't work. Good news, my game didn't crash. I tested with and without other mods.

Edit: 8:32am
After testing a few versions, I am going to take a break for now.
Of course it is not working, but I feel confident that I can do it. If I can't, then I may as well change my major something else.
Ms. Byte (Deceased)
#9 Old 29th Nov 2013 at 5:49 PM
At this stage it would be better to upload your code instead of a package, so people don't have to extract the dll and use a decompiler.

Before going any further you need to figure out how this is going to function. You need some way to detect when a sim calls a taxi, have an event handler for it, and do your calculations and deduct the fee then. Your world load event handler calls a function that returns a bool, which doesn't appear to do anything. I don't see anything that invokes your Payments method, unless I'm missing something. Unfortunately I don't see any game event for when a taxi is called or used. It might be possible to inject your code when a taxi is instantiated by overriding the CarNPC constructor, but I don't know specifically how to do that. You could look at the NRaas code; a lot of Twallan's mods replace EA code.

Please do not PM me with mod, tutorial, or general modding questions or problems; post them in the thread for the mod or tutorial or post them in the appropriate forum.

Visit my blogs for other Sims content:
Online Sims - general mods for Sims 3
Offline Sims - adult mods for Sims 3 and Sims 4
Field Researcher
#10 Old 28th Jan 2014 at 8:40 PM Last edited by Sleepy-Genius : 10th Feb 2014 at 4:16 AM.
Default Update.
Well Ms. Byte, So I don't think this is looking good...

I always get stuck on how to return the fee.
I'm sure you'll see the other errors.

Here is what I have so far.
Ms. Byte (Deceased)
#11 Old 5th Feb 2014 at 6:09 PM
I'm not following the logic of your code:

Using the kVisitLot event would mean your taxi method would fire every time a sim visits a lot, whether or not he/she took a taxi. It makes more sense to me to use the kUsedVehicle event and test the e.TargetObject to see if it's a taxi. You can get the sim using the taxi by casting e.Actor as a sim and you can get the list of all the sims in the taxi. That part would look like this:

Sim sim = e.Actor as Sim;
List<Sim> simList;
if (e.TargetObject is Taxi)
{
Taxi taxi = e.TargetObject as Taxi;
simList = taxi.ActorsUsingMe;
}
else
{
return ListenerAction.Keep;
}

Then of course if you want to charge more for extra passengers you need logic to go through the list of sims and charge appropriately without charging twice for the main passenger, and without charging for the driver if he/she is in the list.

Sims3.Gameplay.Actors.Sim.ActiveActor.CanDriveOrCallTaxi(); : You have this in your onWorldLoadFinished handler and your handler for the taxi event. This is a bool; it needs an if statement to actually do anything. In the OnWorldLoadFinished I don't see any function for it since you're not adding an interaction to a sim. In your method to be called when the sim takes a taxi, it seems irrelevant to test whether or not he/she is allowed to use a taxi if he/she has already used one. Also the way it's written this is a static method and not testing the specific sim who's using a taxi.

fee = kAdultFee * (int)SimClock.ConvertToTicks(1f, TimeUnit.Seconds); : This will always multiply the fee times the number of ticks in 1 second. Besides that this may turn out to be an amount you don't want, why bother multiplying by the same thing instead of just using kAdultFee? In fact I don't see any way of detecting how long the taxi ride was so charging a flat fee may be the only way to handle this. (You could experiment with the many, many methods/properties of the Taxi class, though, to see if you can get a trip length.)

World.OnLotAddedEventHandler += new EventHandler(TaxiCharge.OnWorldLoadFinished); : What's the purpose of this? You don't have to start the script again every time a lot is added to the world.

When I left "Sims3.Gameplay.Actors.Sim.ActiveActor.CanDriveOrCallTaxi();" and "World.OnLotAddedEventHandler += new EventHandler(TaxiCharge.OnWorldLoadFinished);" in my test version of your script, all the adults in my game vanished.

You don't need kInstantiator since you've got at least one other tunable variable (kAdultFee).

I did a test using the suggestions above and it does work.

Please do not PM me with mod, tutorial, or general modding questions or problems; post them in the thread for the mod or tutorial or post them in the appropriate forum.

Visit my blogs for other Sims content:
Online Sims - general mods for Sims 3
Offline Sims - adult mods for Sims 3 and Sims 4
Field Researcher
#12 Old 6th Feb 2014 at 8:53 AM Last edited by Sleepy-Genius : 10th Feb 2014 at 4:15 AM.
Well, I knew what I wanted to do, but I was (still am somewhat) having a problem translating in a way the game would recognize it. It's frustrating. Whenever I think I have this problem fixed, VS gives me this new error / warning, and I will have to change everything.

The "layout" you gave me a few posts back, was what I was attempting to follow, but once again, got stuck.

I used kVisitLot because I was thinking it meant if a sim wanted to visit it a lot, it would call a taxi and visit the lot. Something like that.

For the kAdultFee, I wanted the fee to be multiplied by the seconds/minutes it took for the taxi to reach destination; but a flat fee may work also. Later on, I want to have different fee for the ages Elder - Teen. That is why i named the variable kAdultFee.

I honestly don't know where my mind was adding World.OnLotAddedEventHandler. I really don't.

The Sims3.Gameplay.Actors.Sim.ActiveActor.CanDriveorCallTaxi(), I was trying to "call" like you would a function. Yes, I know, wrong programming language. I thought by adding that, the way it is, the code would run if "called".

I tried to build the new edits, but I cannot figure out these 2 errors:

The top error is for the lowercase sim in 'Sim sim = e.Actor as Sim;'

I also couldn't compile a dll file in the release folder because of them, so I could not test it.
Ms. Byte (Deceased)
#13 Old 6th Feb 2014 at 3:34 PM
Error 2 : You have 'sim' defined as an argument passed into the InUsedVehicle method, and then defined again in the InUsedVehicle code.

Error 3 : As you might guess from the name, ProcessEventDelegate is a delegate method. Delegates are a way of passing another method as an argument, most often used to set up event handlers as in this case. The method that's passed must have the same 'signature' - the same return type and arguments - as the delegate method. If you use Reflector or ILSpy to look at the game code, you'll see that ProcessEventDelegate is declared as:

public delegate ListenerAction ProcessEventDelegate(Event e)

This means the method you use with it must have an Event as the only argument and must return a ListenerAction. You're using InUsedVehicle with it, and your declaration of InUsedVehicle is:

private static ListenerAction InUsedVehicle(Event e, SimDescription sim)

The arguments are wrong - it can only take the Event. Remove SimDescription sim and that should resolve both your errors.

BTW, the warning you're getting may mean you don't have the project set up correctly. Possibly you have mscorlib twice in your References. If so, make sure you keep only the EA version.

Other notes:

You know GetInCarPassenger is not being called anywhere, right?

The usual practice is to define a variable when you use EventTracker.AddListener, like this:

In the main class definition : private static EventListener sSimVehicle = null;
And the call in OnWorldLoadFinished : sSimVehicle = EventTracker.AddListener(EventTypeId.kUsedVehicle, new ProcessEventDelegate(InUsedVehicle));

I'm not sure this is necessary, but it might be to ensure the instantiation of the listener doesn't go away as soon as OnWorldLoadFinished exits. I've never tested so I don't know.

Quote:
The Sims3.Gameplay.Actors.Sim.ActiveActor.CanDriveorCallTaxi(), I was trying to "call" like you would a function. Yes, I know, wrong programming language. I thought by adding that, the way it is, the code would run if "called".


C# will call a method like this, yes. The question is, what did you expect running Sims3.Gameplay.Actors.Sim.ActiveActor.CanDriveorCallTaxi() would do? All this method does is test the currently active (selected) sim to see if he/she is the right age to be able to call a taxi, and return a bool. Without an if statement it will still do that but since the bool isn't being used it doesn't serve any useful purpose.

Looks like you can fix the arguments of InUsedVehicle and (maybe) define a variable for your listener, and it should work.

Please do not PM me with mod, tutorial, or general modding questions or problems; post them in the thread for the mod or tutorial or post them in the appropriate forum.

Visit my blogs for other Sims content:
Online Sims - general mods for Sims 3
Offline Sims - adult mods for Sims 3 and Sims 4
Field Researcher
#14 Old 7th Feb 2014 at 12:16 AM Last edited by Sleepy-Genius : 7th Feb 2014 at 12:33 AM.
My main problem now: I kept the SimDescription sim because without it, I get:


Now, I cant compile a release at all. With the warning, I can no problem, but not with this error.

Edit: I changed sim.Household.Familyfunds to e.Actor.Household.Familyfunds. I commented out the statement determining the sims.length. It gives me a release.
Ms. Byte (Deceased)
#15 Old 7th Feb 2014 at 4:01 AM
You seem to be working with a version that's different from the one you uploaded. But yes, the right way to get the sim using the vehicle is via e.Actor. I'd have to see your current version of the code to see where you're getting sims, but if you want the list of sims in the vehicle that is available as :

Taxi taxi = e.TargetObject as Taxi;
simList = taxi.ActorsUsingMe;

Please do not PM me with mod, tutorial, or general modding questions or problems; post them in the thread for the mod or tutorial or post them in the appropriate forum.

Visit my blogs for other Sims content:
Online Sims - general mods for Sims 3
Offline Sims - adult mods for Sims 3 and Sims 4
Field Researcher
#16 Old 7th Feb 2014 at 6:17 AM Last edited by Sleepy-Genius : 10th Feb 2014 at 4:15 AM.
Here you go.
It didn't work in game.
Ms. Byte (Deceased)
#17 Old 7th Feb 2014 at 2:55 PM
You changed the main class name; maybe you forgot to update the xml Instance ID?

A few suggestions:

This script will execute whenever any sim in the neighborhood uses any vehicle, which is pretty often. There are a lot more non-taxi vehicles in use than sims without enough family funds to pay for a taxi. I suggest you test the vehicle for being a taxi first, then test the household funds, to make the code more efficient.

Are you planning to use the list of sims (simList)? If not, it wastes resources to get the list.

When developing a script you should have a way to debug and to make sure it's even being loaded by the game. I find the following to be very useful:

StyledNotification.Show(new StyledNotification.Format(<informational message string here>,
StyledNotification.NotificationStyle.kGameMessagePositive));

This will display a message in the little message thingie at the upper right. You can use it to just display "Hello" to make sure your script is running, and you can display whatever other info you need to see if it's working the way you want. In my tests I have the following display when a sim is actually charged for a taxi ride:

StyledNotification.Show(new StyledNotification.Format(sim.Name + " has been charged " + fee.ToString() + " simoleans",
StyledNotification.NotificationStyle.kGameMessagePositive));

Please do not PM me with mod, tutorial, or general modding questions or problems; post them in the thread for the mod or tutorial or post them in the appropriate forum.

Visit my blogs for other Sims content:
Online Sims - general mods for Sims 3
Offline Sims - adult mods for Sims 3 and Sims 4
Field Researcher
#18 Old 8th Feb 2014 at 2:13 PM Last edited by Sleepy-Genius : 10th Feb 2014 at 4:14 AM.
*sigh*

I now understand why I didn't like C# all that well. Sure it was fun creating the applications and all, but wow. And to think I want to do this for a living one day.

But anyway, I have updated, this. I changed the structure of the code. I think I have used simList correctly. I had to look at other codes to know how to use it, because I didn't know what it was for. I originally thought it was to actually list the sims... I also add the string. I had completely forgot about that.

I'm going to test this know.

Edit: It didn't work. I'll try to rearrange it or something...
Ms. Byte (Deceased)
#19 Old 8th Feb 2014 at 3:51 PM Last edited by CmarNYC : 8th Feb 2014 at 4:02 PM.
Much better, and adding the fee to unpaid bills if the sim is broke is a very nice touch. Just one mistake:

List<Sim> simList = new List<Sim>();
simList = taxi.ActorsUsingMe;
foreach (Sim sim2 in simList)
{
if (sim2 != e.Actor)
{
fee = kAdultFee * simList.Count;
}
}

simList is a list of the sims using the taxi - a list of the class 'sim'. I'm not sure what the confusion was, unless you thought it was a list of text names. "foreach (Sim sim2 in simList)" will iterate through the list. What your code is doing is to go through the list and for each sim except your main sim, multiply kAdultFee by the total number of sims. Since I'm pretty sure the list you get from "taxi.ActorsUsingMe" includes the driver, you'll get charged for an extra sim. If it doesn't include the driver and your sim is the only passenger, no calculation will be done. Also, since it's an abstract property inherited from the Object class and I can't find a definition for cars or taxis, it's possible it's not doing what we think it does. I hate abstracts.

After looking at the game code again, the property "Taxi.Passengers" is more appropriate - you know you're getting only the passengers. When you use it you get an array rather than a list:

Sim[] simList = taxi.Passengers;

In fact you don't even need to declare the array; all the code above can be replaced with:

fee = kAdultFee * taxi.Passengers.Length;

Of course, if you want to charge different amounts for elders and children, you'd iterate through the list as you're doing now, test the age of each sim, and add the appropriate amount.


You should not set kAdultFee = 0 - depending on how the game instantiates the event handler it could mean your fee will be 5 the first time and 0 after that.


The logic is the hardest part of programming, no matter what the language is. C# can certainly seem overwhelming at first, but it's also very powerful, and these days a programmer is going to have to learn the more difficult concepts like abstracts and delegates etc. in order to use any advanced language. I'm certainly still struggling with a lot of it myself - I had to look up delegates and figure out what the heck the documentation was talking about before I could try to explain it to you. We both learned something.

Please do not PM me with mod, tutorial, or general modding questions or problems; post them in the thread for the mod or tutorial or post them in the appropriate forum.

Visit my blogs for other Sims content:
Online Sims - general mods for Sims 3
Offline Sims - adult mods for Sims 3 and Sims 4
Field Researcher
#20 Old 8th Feb 2014 at 4:31 PM Last edited by Sleepy-Genius : 8th Feb 2014 at 5:01 PM.
I finally got it to work. When the sim first gets in the taxi, the fee is taken out and the message is shown in the upper right. I first tried this in my main game; didn't work. Then I tried this in an Any Game Starter test game I set up. And it works. There must have been a mod script interfering with my mod in my main game. I'll test again other mods, but it works! I haven't tested it for multiple sims; I just did it for that one sim. I did this twice. Both times the sim was charge with the fee. *sigh of relief*

I knew (?sims).Length would be there somewhere, but I couldn't place it. I had it before when I was trying to multiple the kAdultFee times the total passengers, but I deleted. When you gave me the code for the List<> (thank you by the way), I remember seeing that in come other Sims 3 code, I think it was in one of the modules for Story Progression. Also, I was going to try to use the array for slot[] EA already has for vehicles, but your way seemed like a better and shorter solution. If I take out "taxi.ActorsUsingMe" , I will not be charged at all, and if leave it in, I will? :/
I don't remember a lot about abstracts. It was a while ago since I have taken a C# course.

I didn't want the sims to not take the taxi because they could not afford it. So having them owe it later would be better; however, ever sim should be able to afford 5 simoleons.

So, since I can't use kAdultFee = 0 for CarNPC, do I return the listener, or use something like sim.Household.ModifyFunds(+fee), since we are paying him anyway?

Yes, I am going to the different rates for other ages. I wanted to make sure that this worked for one age first.
Ms. Byte (Deceased)
#21 Old 8th Feb 2014 at 7:00 PM
A List and an array are similar - both are ordered collections of elements but a list has more flexibility. For a list you use .Count to get the number of elements and for an array you use .Length. I suggested using taxi.Passengers instead of taxi.ActorsUsingMe because it'll get you just the passengers.

In this form of the script with just a flat fee you really don't have to multiply anything, just charge the kAdultFee amount. Think the logic through.

Just set fee = 0 or just do the return if you don't want to charge NPCs.

I have no idea why the script would have not worked with the default startup. Scripts don't conflict with each other unless they're using the same namespace and class name or doing something really wrong like deleting other interactions or event listeners. Maybe you changed something between tries.

Please do not PM me with mod, tutorial, or general modding questions or problems; post them in the thread for the mod or tutorial or post them in the appropriate forum.

Visit my blogs for other Sims content:
Online Sims - general mods for Sims 3
Offline Sims - adult mods for Sims 3 and Sims 4
Field Researcher
#22 Old 9th Feb 2014 at 3:34 AM Last edited by Sleepy-Genius : 10th Feb 2014 at 4:14 AM.
Since I am more familiar with for loops, I changed the foreach loop to a for. Now it looks like this:
Code:
for (int i = 1; i > simList.Length; i++)
{
sim.Household.ModifyFamilyFunds(-fee);
}


I'll add the age differences after this test run.

Edit: When I call the taxi, the game freezes. She was a park and was sending her home. While she was at the curb, the game froze. I tried this version twice. The version before didn't do this. I think it had something to do with the e.taxiobject being taken out. I could not leave that in the code without having syntax errors, specially with this new loop.
Ms. Byte (Deceased)
#23 Old 9th Feb 2014 at 2:19 PM Last edited by CmarNYC : 9th Feb 2014 at 3:23 PM.
for (int i = 1; i > simList.Length; i++)

Should be:

for (int i = 0; i < simList.Length; i++)

With the >, if simList.Length is 0 your loop will never end and your game hangs. And, C# arrays start with index 0. If you start with 1 you'll only get charged if there's more than one passenger.

My guess is that the game seems to be firing the event with 0 passengers when the taxi is instantiated, with the NPC driver as the actor sim. Then it's fired again when your sim uses the taxi.

I assume you know you're charging twice. The household funds test should be inside the loop

There's no e.taxiobject. ??

Please do not PM me with mod, tutorial, or general modding questions or problems; post them in the thread for the mod or tutorial or post them in the appropriate forum.

Visit my blogs for other Sims content:
Online Sims - general mods for Sims 3
Offline Sims - adult mods for Sims 3 and Sims 4
Field Researcher
#24 Old 10th Feb 2014 at 1:18 AM Last edited by Sleepy-Genius : 12th Feb 2014 at 3:08 AM.
Quote: Originally posted by CmarNYC
for (int i = 1; i > simList.Length; i++)
Should be:
for (int i = 0; i < simList.Length; i++)

Ah, yes. I knew it look funny.
Quote: Originally posted by CmarNYC
I assume you know you're charging twice. The household funds test should be inside the loop

So, would it be legal to put the whole calculation in the for loop then? Because that is what I did in this update.
Quote: Originally posted by CmarNYC
There's no e.taxiobject. ??

Oh wait. I meant to say I got rid of simList = taxi.ActorsUsingMe; . Not Taxi taxi = e.TargetObject as Taxi; <- that is still in there.


E D I T: Okay...so, by putting the if statements for payments in the loop, it *sigh* multiplied the payment times the sims.
For example.
First sim = pays 5, 1 payment
Second sim = pays 10, 2 payments (including first sim)
Third sim = pays 15, 3 payments (including first and second sim)
---------------------------
Total of 30 dollars for taxi ride. 6 separate payments.

That was not my plan, but I may have figured out a way. I will take out payment function from the loop.
At least it works.
Ms. Byte (Deceased)
#25 Old 10th Feb 2014 at 6:59 AM
You really should try to figure out where your logic was wrong. Debugging is a huge part of programming.

Anyway, here's another way to do it.

Fee = 0
For each sim in the list, loop
If adult, fee += adultFee
If elder, fee += elderFee
If child, fee += childFee
End loop
If fee <= funds, charge fee
Else add to bills

Please do not PM me with mod, tutorial, or general modding questions or problems; post them in the thread for the mod or tutorial or post them in the appropriate forum.

Visit my blogs for other Sims content:
Online Sims - general mods for Sims 3
Offline Sims - adult mods for Sims 3 and Sims 4
Page 1 of 3
Back to top