nightingale

[1.6.x+] Contract Configurator [v1.27.1] [2018-12-28]

Recommended Posts

Now that I have polluted the other thread with duration stuff.. Figured I should drop this here.

Based on what I read, I'm changing from this:

	PARAMETER
{
name = Orbit
type = VesselParameterGroup
define = Orbiter
title = Orbit @targetBody
completeInSequence = true
duration = 60m

PARAMETER
{
name = NewVessel
type = NewVessel
}

PARAMETER
{
name = HasCrew
type = HasCrew
minCrew = 1
}

PARAMETER
{
name = Orbit
type = Orbit
minPeA = @targetBody.AtmosphereAltitude() * 1.1
}


}

PARAMETER
{
name = Home
type = VesselParameterGroup
vessel = Orbiter
title = Optionally orbit for 1d, or just return home.
completeInSequence = true

PARAMETER
{
name = Orbit
type = Orbit
minPeA = @targetBody.AtmosphereAltitude() * 1.1
}

PARAMETER
{
name = Duration
type = Duration
duration = 1d
optional = true
notes = (Optional) A longer orbit (1 day) gives extra rewards.

preWaitText = Orbiting for a additional day will provide us with some valuable data.
waitingText = One more day should do.
completionText = Excellent, this will be very helpful.
rewardFunds = 6250 / @targetBody.Multiplier()
rewardScience = 2 / @targetBody.Multiplier()
}

PARAMETER
{
name = ReturnHome
type = ReturnHome
}
}

To this:


PARAMETER
{
name = Orbit
type = VesselParameterGroup
title = Orbit @targetBody

PARAMETER
{
name = NewVessel
type = NewVessel
}

PARAMETER
{
name = HasCrew
type = HasCrew
minCrew = 1
}

PARAMETER
{
name = Orbit
type = Orbit
minPeA = @targetBody.AtmosphereAltitude() * 1.1
}

PARAMETER
{
name = Duration
type = Duration
duration = 1d
optional = true
notes = (Optional) A longer orbit (1 day) gives extra rewards.

preWaitText = Orbiting for a additional day will provide us with some valuable data.
waitingText = One more day should do.
completionText = Excellent, this will be very helpful.
rewardFunds = 6250 / @targetBody.Multiplier()
rewardScience = 2 / @targetBody.Multiplier()
}

PARAMETER
{
name = ReturnHome
type = ReturnHome
}
}

Seem good?

Share this post


Link to post
Share on other sites
Now that I have polluted the other thread with duration stuff.. Figured I should drop this here.

Based on what I read, I'm changing from this:

<snip>

Seem good?

Yes... but I thought of an exploit/issue that I'll work to fix in 1.7.1. If a player were to get to orbit, wait out the timer, and then fails to return home (let's say he forgets his chute). In that scenario, the Duration parameter would stay checked and the player would be able to launch a follow up mission without having to do the duration portion. Raised [#308] for that.

Also - I have no idea if an optional parameter works within a vessel parameter group. Test it and get back to me, and if it doesn't work I'll fix that too.

Share this post


Link to post
Share on other sites

Not sure what is wrong, but just tested the second one and the duration counts down just fine, but for whatever reason if you want to skip the duration it doesn't let you.

Share this post


Link to post
Share on other sites
Not sure what is wrong, but just tested the second one and the duration counts down just fine, but for whatever reason if you want to skip the duration it doesn't let you.

Yup, that means optional parameters do not work within a VPG. But... I'm gonna say that's working as designed. Because you don't want optional parameters in there - because they can flip on/off based on what ship is selected, the giving the player the opportunity to get the optional reward multiple times.

Here's the alternative I would suggest:

PARAMETER
{
name = Orbit
type = VesselParameterGroup
title = Orbit @targetBody

PARAMETER
{
name = NewVessel
type = NewVessel
}

PARAMETER
{
name = HasCrew
type = HasCrew
minCrew = 1
}

PARAMETER
{
name = Orbit
type = Orbit
minPeA = @targetBody.AtmosphereAltitude() * 1.1
}

PARAMETER
{
name = ReturnHome
type = ReturnHome
}
}


PARAMETER
{
name = OptionalDuration
type = VesselParameterGroup
title = (Optional) A longer orbit (1 day) gives extra rewards.

rewardFunds = 6250 / @targetBody.Multiplier()
rewardScience = 2 / @targetBody.Multiplier()

PARAMETER
{
name = NewVessel
type = NewVessel
}

PARAMETER
{
name = HasCrew
type = HasCrew
minCrew = 1
}

PARAMETER
{
name = Orbit
type = Orbit
minPeA = @targetBody.AtmosphereAltitude() * 1.1
}

PARAMETER
{
name = Duration
type = Duration
duration = 1d
optional = true

preWaitText = Orbiting for a additional day will provide us with some valuable data.
waitingText = One more day should do.
completionText = Excellent, this will be very helpful.
}
}

There's a little bit of duplication, but I don't see a good way to do it otherwise without reverting back to the define/vessel mess.

Share this post


Link to post
Share on other sites

Ok, the first part makes sense.

But I'm confused about the define vessel thing. I use that for quite a few of the contracts that I've made specifically so that I can setup a good amount of optional stuff. Plus so far it seems like the return home parameter is better in a defined vessel group. Or am I wrong? I do admit I have to do more testing. :)

Share this post


Link to post
Share on other sites
Ok, the first part makes sense.

But I'm confused about the define vessel thing. I use that for quite a few of the contracts that I've made specifically so that I can setup a good amount of optional stuff. Plus so far it seems like the return home parameter is better in a defined vessel group. Or am I wrong? I do admit I have to do more testing. :)

The define + vessel construct has some limitations, so it should be avoided whenever possible. That's why being able to put the Duration parameter inside the VPG is such a good thing. Some of the problems that can arise in a typical chain of two VPG parameters with the first doing define=someVessel and the second doing vessel=someVessel:

  1. If a player gets a vessel defined in the first VPG, and then messes up (lets say they explode the vessel, somehow), then they can't complete the contract. The workaround to this is to set disableOnStateChange=false for the first VPG... but that won't work in this case, as the first VPG would then "uncomplete" when you go out of orbit.
  2. I'm not convinced it's always clear to the player what's expected of them. I have the (New) and (TBD) labels that get put in the text to help that along... but I think it's still pretty murky. I think a lot of people also assume that their ship name needs to match the one in the parameter, which is most definitely not true.

In fact, the "chaining" ability was really intended for something where a single vessel crosses multiple contracts (example: KSS). I'm not saying don't ever use it this way, as sometimes it really is the way to do something... just use with caution, and prefer other options when they are available.

For the specific case of the ReturnHome, the two VPGs has always been the way to do it... I'm hoping to change that with these changes to Duration in the last couple releases, because it'll make more streamlined contracts for a very common use case.

Share this post


Link to post
Share on other sites

Ok, that makes a lot of sense and if it works how I'm thinking, it should clean up my contracts a lot...

So just to verify, this change mean I can completely remove the second vessel group, move all of my stuff together, and instead use duration.. Making:

This: https://github.com/NoriSilverrage/Refined-Progression/blob/a6c83ecb178b724eb14b65d23797c56b052835d7/GameData/ContractPacks/RefinedProgression/03-CloseEncounters/002-CloseOrbits.cfg

Into this:

https://github.com/NoriSilverrage/Refined-Progression/blob/master/GameData/ContractPacks/RefinedProgression/03-CloseEncounters/002-CloseOrbits.cfg

PS: I promise I'll stop asking questions about duration... :P

Share this post


Link to post
Share on other sites
Ok, that makes a lot of sense and if it works how I'm thinking, it should clean up my contracts a lot...

So just to verify, this change mean I can completely remove the second vessel group, move all of my stuff together, and instead use duration.. Making:

This: https://github.com/NoriSilverrage/Refined-Progression/blob/a6c83ecb178b724eb14b65d23797c56b052835d7/GameData/ContractPacks/RefinedProgression/03-CloseEncounters/002-CloseOrbits.cfg

Into this:

https://github.com/NoriSilverrage/Refined-Progression/blob/master/GameData/ContractPacks/RefinedProgression/03-CloseEncounters/002-CloseOrbits.cfg

PS: I promise I'll stop asking questions about duration... :P

I'd move the optional parameters out on their own though - optional parameters in a VPG will give you grief (they'll prevent the VPG from completing if they aren't done, will still "work" even for a vessel that meets the other criteria, and will be repeatable multiple times for extra funds).

Also, I think the one where you have the Any should be an all (or just the CollectScience, since you don't really need the landing part).

Share this post


Link to post
Share on other sites
I'd move the optional parameters out on their own though - optional parameters in a VPG will give you grief (they'll prevent the VPG from completing if they aren't done, will still "work" even for a vessel that meets the other criteria, and will be repeatable multiple times for extra funds).

Also, I think the one where you have the Any should be an all (or just the CollectScience, since you don't really need the landing part).

Huh. Well that would explain some of the issues I've had. :P

Not sure if this would be a issue for these types of optional parameters... But if I put the optional parameters outside of the VPG wouldn't they then be completable by a vessel outside of the one that meets the previous parameters? Again, for optional ones like this I'm not sure if it matters, but from a structure standpoint it seems a bit odd I guess.

Also, if I wanted to add a optional duration wouldn't I then need it to be in a VPG since a vessel is only tracked if active outside of one?

Share this post


Link to post
Share on other sites
Huh. Well that would explain some of the issues I've had. :P

Not sure if this would be a issue for these types of optional parameters... But if I put the optional parameters outside of the VPG wouldn't they then be completable by a vessel outside of the one that meets the previous parameters? Again, for optional ones like this I'm not sure if it matters, but from a structure standpoint it seems a bit odd I guess.

Also, if I wanted to add a optional duration wouldn't I then need it to be in a VPG since a vessel is only tracked if active outside of one?

Yup, exactly. So that pretty much forces you back to the whole define/vessel stuff if you want to have tons and tons of optional parameters like that. :)

Share this post


Link to post
Share on other sites

Another pre-release since there were a couple more big risky changes. I don't expect any issues, and should be changing this to a full release in a day or two. Download now!

Contract Configurator 1.7.1

  • Fixed a backwards compatibility issue introduced in 1.7.0 (thanks Ald).
  • When title isn't overriden, prefix optional parameters with "(Optional)".
  • Added a hidden attribute for all parameters.
  • VesselParameterGroups now list out vessels that can complete the contract more clearly.
  • Fixed output text when converting a duration to a string in contracts.
  • Improved behaviour of Duration parameter when used under VesselParameterGroup.

Share this post


Link to post
Share on other sites

Any idea why this doesn't evaluate properly:


DATA
{
type = double

diffModifier2 = Prestige() == Trivial ? 0 : Prestige() == Significant ? 10 : 20
}

When a contract is trivial it comes out right, with 0, but either significant or exceptional both come out with 20. I've tried it is part of a DATA node or within a PARAMETER node, neither seems to work.


CONTRACT_TYPE
{
name = SCAN_Biome
title = Do a Biome Scan of @/targetBody2
group = ScanSatOfficial
agent = SCAN: Scientific Committee on Advanced Navigation
topic = Science
subject = Kerbal
motivation = Scanning
notes = Scanning can take place while the vessel is not loaded.
synopsis = Perform a MultiSpectral scan of @/targetBody2
completedMessage = Stunning, through the advances with this scanner we have identified several different biomes for further study.
minExpiry = 1
maxExpiry = 7
deadline = Random(500, 1000)
cancellable = true
declinable = true
autoAccept = false
targetBody = @/targetBody2
// Contract rewards
rewardScience = 0
rewardReputation = 1
rewardFunds = Random(40000, 60000.0)
failureReputation = 1
failureFunds = Random(1, 10000.0)
advanceFunds = Random(1, 10000.0)

DATA
{
type = CelestialBody
requiredValue = true
uniqueValue = true
targetBody2 = Prestige() == Trivial ? @ScanSatOfficial:p1Bodies.Random() : Prestige() == Significant ? @ScanSatOfficial:p2Bodies.Random() : @ScanSatOfficial:p3Bodies.Random()
}

DATA
{
type = double

diffModifier2 = Prestige() == Trivial ? 0 : Prestige() == Significant ? 10 : 20
scanRequired2 = 75 + @diffModifier2
minScan2 = 74.9 + @diffModifier2
}

PARAMETER
{
name = SCANsatCoverage
type = SCANsatCoverage
targetBody = @/targetBody2
coverage = @/scanRequired2
scanType = Biome
}
REQUIREMENT
{
name = SCANsatCoverage
type = SCANsatCoverage
targetBody = @/targetBody2
minCoverage = 0.0
maxCoverage = @/minScan2
scanType = Biome
}
REQUIREMENT
{
name = PartUnlocked
type = PartUnlocked
part = SCANsat_Scanner24
}
}

Share this post


Link to post
Share on other sites
Any idea why this doesn't evaluate properly:


DATA
{
type = double

diffModifier2 = Prestige() == Trivial ? 0 : Prestige() == Significant ? 10 : 20
}

When a contract is trivial it comes out right, with 0, but either significant or exceptional both come out with 20. I've tried it is part of a DATA node or within a PARAMETER node, neither seems to work.


CONTRACT_TYPE
{
name = SCAN_Biome
title = Do a Biome Scan of @/targetBody2
group = ScanSatOfficial
agent = SCAN: Scientific Committee on Advanced Navigation
topic = Science
subject = Kerbal
motivation = Scanning
notes = Scanning can take place while the vessel is not loaded.
synopsis = Perform a MultiSpectral scan of @/targetBody2
completedMessage = Stunning, through the advances with this scanner we have identified several different biomes for further study.
minExpiry = 1
maxExpiry = 7
deadline = Random(500, 1000)
cancellable = true
declinable = true
autoAccept = false
targetBody = @/targetBody2
// Contract rewards
rewardScience = 0
rewardReputation = 1
rewardFunds = Random(40000, 60000.0)
failureReputation = 1
failureFunds = Random(1, 10000.0)
advanceFunds = Random(1, 10000.0)

DATA
{
type = CelestialBody
requiredValue = true
uniqueValue = true
targetBody2 = Prestige() == Trivial ? @ScanSatOfficial:p1Bodies.Random() : Prestige() == Significant ? @ScanSatOfficial:p2Bodies.Random() : @ScanSatOfficial:p3Bodies.Random()
}

DATA
{
type = double

diffModifier2 = Prestige() == Trivial ? 0 : Prestige() == Significant ? 10 : 20
scanRequired2 = 75 + @diffModifier2
minScan2 = 74.9 + @diffModifier2
}

PARAMETER
{
name = SCANsatCoverage
type = SCANsatCoverage
targetBody = @/targetBody2
coverage = @/scanRequired2
scanType = Biome
}
REQUIREMENT
{
name = SCANsatCoverage
type = SCANsatCoverage
targetBody = @/targetBody2
minCoverage = 0.0
maxCoverage = @/minScan2
scanType = Biome
}
REQUIREMENT
{
name = PartUnlocked
type = PartUnlocked
part = SCANsat_Scanner24
}
}

It's a bug in the parser. It was converting Prestige() to a double and then treating Trivial as a stored identifier (which it wouldn't find so it would assign the value zero). Same for the other portions of the expression.

Anyway, fix it done, it'll be released when 1.7.2 comes out (most likely looking at tomorrow).

Share this post


Link to post
Share on other sites
It's a bug in the parser. It was converting Prestige() to a double and then treating Trivial as a stored identifier (which it wouldn't find so it would assign the value zero). Same for the other portions of the expression.

Anyway, fix it done, it'll be released when 1.7.2 comes out (most likely looking at tomorrow).

Groovy.

Will that affect other instances of using that syntax? Like what you have for selecting target bodies for Field Research. I'm using a similar method, but haven't really gotten around to testing if it's actually working.

Share this post


Link to post
Share on other sites
Groovy.

Will that affect other instances of using that syntax? Like what you have for selecting target bodies for Field Research. I'm using a similar method, but haven't really gotten around to testing if it's actually working.

Nope, it will only affect numeric types (and any numeric but double will probably fail with an exception). Because Contract.ContractPrestige isn't convertible to CelestialBody, it won't even try, and it'll get it right.

Share this post


Link to post
Share on other sites

Hey nightingale,

I keep getting this error pop up across many contracts and I'm pretty sure it's causing hangs I'm having:

[Log]: [DEBUG] ContractConfigurator.ContractPreLoader: Contract attribute took too long (0.1254883 seconds) to generate: HM_Skylab3[targetMars]

It's in reference to this (from a contract group)


DATA
{
type = CelestialBody

targetMars = AllBodies().Where(p => p.Name() == "Duna" || p.Name() == "Mars").Random()
requiredValue = false
}

Happened with both contract configurator 1.7.0 and 1.7.1 (also have HyperEdit installed)

Including player.log (I'm on mac) and gamedata for reference

Thought I'd point this out to you, but going to change this code anyway as I think it's a pretty terrible way of doing what I want :)

Share this post


Link to post
Share on other sites
Hey nightingale,

I keep getting this error pop up across many contracts and I'm pretty sure it's causing hangs I'm having:

[Log]: [DEBUG] ContractConfigurator.ContractPreLoader: Contract attribute took too long (0.1254883 seconds) to generate: HM_Skylab3[targetMars]

It's in reference to this (from a contract group)


DATA
{
type = CelestialBody

targetMars = AllBodies().Where(p => p.Name() == "Duna" || p.Name() == "Mars").Random()
requiredValue = false
}

Happened with both contract configurator 1.7.0 and 1.7.1 (also have HyperEdit installed)

Including player.log (I'm on mac) and gamedata for reference

Thought I'd point this out to you, but going to change this code anyway as I think it's a pretty terrible way of doing what I want :)

Change .Random() to .First() (since there will only ever be one). That way Contract Configurator will know that targetMars is a constant value and will only load it once at parse time (at game startup).

If you're still having the slowdowns after that I'll take a closer look.

EDIT: Took a quick look and didn't see anything else jumping out. I will mention that you're in unexplored territory in terms of performance - WhiteCat's original version of the historical contracts had a massive amount of contracts, but they were all fairly simple. As complexity increases there's definitely going to be some degradation in the contract generation performance - but hopefully if there's any places that need some tweaking/improvements this will help find it.

Edited by nightingale

Share this post


Link to post
Share on other sites

New release, first non-prerelease of the 1.7.x branch (including the 1.7.0 and 1.7.1 changelogs as reference). Download now!

Contract Configurator 1.7.2

  • DialogBox behaviour now supports loading/unloading textures for images on the fly.
  • Fixed issue with dialog boxes that weren't getting positioned correctly.
  • Fixed issue with SpawnVessel when switching from editor to flight scene (introduced in 1.7.0).
  • Fixed parser issue with early data type conversions (thanks DMagic).
  • Fixed issue with hidden parameters in Sequence not working in Contracts Window + (thanks 5thHorseman).
  • Misc bug fixes.

Contract Configurator 1.7.1

  • Fixed a backwards compatibility issue introduced in 1.7.0 (thanks Ald).
  • When title isn't overriden, prefix optional parameters with "(Optional)".
  • Added a hidden attribute for all parameters.
  • VesselParameterGroups now list out vessels that can complete the contract more clearly.
  • Fixed output text when converting a duration to a string in contracts.
  • Improved behaviour of Duration parameter when used under VesselParameterGroup.

Contract Configurator 1.7.0

  • New DialogBox behaviour for creating rich text dialog boxes with images.
  • New CopyCraftFile behaviour to reward a player with a craft file.
  • New DestroyVessel behaviour to destroy a vessel.
  • New RecoverVessel parameter.
  • Support in WaypointGenerator for underwater waypoints.
  • Duration parameter can now be used as a child of some parameters.
  • Duration parameter now respects the vessel filter in VesselParameterGroup.
  • Expression behaviour can now store data for types other than double.
  • Data can now be retrived from the persistent data store in expressions using the $ symbol.
  • Improved casting between string and VesselIdentifier (thanks Nori).
  • Made ChageVesselOwnership onState values consistent with other behaviours.
  • Added Crawlerway into list of KSC biomes for contracts (thanks Rokanov).
  • Fixed issue with grandparent contract groups not being recognized properly for expressions (thanks Rokanov).
  • Fixed issues spawning vessels with the deferredVesselCreation flag (thanks Enceos).
  • Fixed exception in HasCrew when referencing a Kerbal that hasn't yet been spawned (thanks severedsolo).

Share this post


Link to post
Share on other sites
Support in WaypointGenerator for underwater waypoints.

Wait a sec... We underwater now? Did I miss something?

Share this post


Link to post
Share on other sites

I think I messed up my game somewhere, but contracts aren't working and gives me this error when I try to load my quicksave. Says to post it here, so here I am.

Exception occured while loading ScenarioModule 'ContractPreLoader':System.ArgumentOutOfRangeException: Argument is out of range.
Parameter name: index
at System.Collections.Generic.List`1[Contracts.Agents.Agent].get_Item (Int32 index) [0x00000] in <filename unknown>:0
at Contracts.Agents.AgentList.GetAgentRandom () [0x00000] in <filename unknown>:0
at Contracts.Contract.Load (Contracts.Contract contract, .ConfigNode node) [0x00000] in <filename unknown>:0
at ContractConfigurator.ContractPreLoader.OnLoad (.ConfigNode node) [0x00000] in <filename unknown>:0

Share this post


Link to post
Share on other sites
I think I messed up my game somewhere, but contracts aren't working and gives me this error when I try to load my quicksave. Says to post it here, so here I am.

Exception occured while loading ScenarioModule 'ContractPreLoader':System.ArgumentOutOfRangeException: Argument is out of range.
Parameter name: index
at System.Collections.Generic.List`1[Contracts.Agents.Agent].get_Item (Int32 index) [0x00000] in <filename unknown>:0
at Contracts.Agents.AgentList.GetAgentRandom () [0x00000] in <filename unknown>:0
at Contracts.Contract.Load (Contracts.Contract contract, .ConfigNode node) [0x00000] in <filename unknown>:0
at ContractConfigurator.ContractPreLoader.OnLoad (.ConfigNode node) [0x00000] in <filename unknown>:0

Interesting, but I'll need more info, especially since that particular error is coming out of Squad's code. Could you provide a KSP.log file? Also, did this only start happening on 1.7.2? If you revert back to 1.6.6 does the error go away?

Share this post


Link to post
Share on other sites

No, it doesn't go away using 1.6.6. As I said, I believe I messed up the game somehow, but being new to KSP and its modding community, I'm not entirely sure how it differs from say the Skyrim or Minecraft modding communities so I'm just following instructions. Anywho, here's the log.

Also, I'm forcing the OpenGL version as the game crashes on load with the normal 32 bit with out of memory errors, not sure how relevant that is though.

I did notice that this started happening after I used the DDSLoader from CKAN and the DDS converter tool made for it. Not entirely sure how a graphics mod can affect code though.

Share this post


Link to post
Share on other sites
No, it doesn't go away using 1.6.6. As I said, I believe I messed up the game somehow, but being new to KSP and its modding community, I'm not entirely sure how it differs from say the Skyrim or Minecraft modding communities so I'm just following instructions. Anywho, here's the log.

Also, I'm forcing the OpenGL version as the game crashes on load with the normal 32 bit with out of memory errors, not sure how relevant that is though.

I did notice that this started happening after I used the DDSLoader from CKAN and the DDS converter tool made for it. Not entirely sure how a graphics mod can affect code though.

You probably converted an agency logo to DDS. Don't do that.

That converter somehow screws up the small agency logo images when converting from PNG to DDS, the only safe way that I know of to convert those is through PhotoShop with nVidia's texture tools. Otherwise those small agency logos should be left alone.

Share this post


Link to post
Share on other sites
You probably converted an agency logo to DDS. Don't do that.

That converter somehow screws up the small agency logo images when converting from PNG to DDS, the only safe way that I know of to convert those is through PhotoShop with nVidia's texture tools. Otherwise those small agency logos should be left alone.

Aight, well I deleted the loader, got rid of the converter and ran a verify through steam to put it back to a more or less default state. The error still comes up.

EDIT: Did a clean re-install and that fixed it, but it's curious why that happened.

Edited by Budz42

Share this post


Link to post
Share on other sites
Wait a sec... We underwater now? Did I miss something?

It's doable, but not something I've ever attempted. Fengeist is probably the expert in on/under water adventures.

- - - Updated - - -

EDIT: Did a clean re-install and that fixed it, but it's curious why that happened.

Essentially when any one of the agent graphics fails loading, it'll take down the whole subsystem with it. No agencies means no contracts. :(

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.